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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers frq_cuntr_f746.cpp Source File

frq_cuntr_f746.cpp

00001 /*
00002  * mbed Library / Frequency Counter with GPS 1PPS Compensation
00003  *      Frequency Counter Hardware relataed program
00004  *      Only for ST Nucleo-F746ZG
00005  *
00006  * Copyright (c) 2014,'15,'16 Kenji Arai / JH1PJL
00007  *  http://www.page.sannet.ne.jp/kenjia/index.html
00008  *  http://mbed.org/users/kenjiArai/
00009  *      Started:    October   18th, 2014
00010  *      Revised:    January    1st, 2015
00011  *      Re-started: June      25th, 2016    ported from F411 board
00012  *      Revised:    Novemeber 23rd, 2016
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00015  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00016  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00017  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00018  * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
00019  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
00020  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00021  */
00022 
00023 #if !defined(TARGET_STM32F746ZG)
00024 #error "This function works only on F746ZG!!"
00025 #endif  // !defined(TARGET_STM32F746ZG)
00026 
00027 #include    "frq_cuntr_f746.h"
00028 #include    "RingBuff.h"
00029 
00030 #define     ACTIVE_LED      1
00031 
00032 #if ACTIVE_LED
00033 DigitalOut irq_led1(LED1);
00034 DigitalOut irq_led2(LED2);
00035 DigitalOut irq_led3(LED3);
00036 #endif
00037 
00038 #if DEBUG
00039 #define PRINTF(...)     printf(__VA_ARGS__)
00040 #else
00041 #define PRINTF(...)     {;}
00042 #endif
00043 
00044 namespace Frequency_counter
00045 {
00046 
00047 // Following ring buffers are very big!! 4096 x 8(bytes) x 2(buff) = 64KB
00048 RingBuff<uint64_t> onepps_buf;    // RinBuffer for 1PPS (TIM2)
00049 freq_one onepps_dt;                 // frequency data in pack (interrupt)
00050 RingBuff<uint64_t> fdt_buffer;    // RinBuffer for TIM8+4
00051 freq_one fdt;                       // frequency data in pack (interrupt)
00052 
00053 // TIM2 IC2 + OverFlow
00054 static uint8_t  tim2_ready_flg;
00055 static uint32_t tim2_cnt_data;
00056 static uint16_t time_count_onepps;
00057 static uint16_t sw_ovrflw_tim2;
00058 // TIM2 IC4 (Reciprocal)
00059 static uint8_t  recipro_step;
00060 static uint32_t recipro_start;
00061 static uint32_t recipro_stop;
00062 // TIM2 OC
00063 static uint32_t oc_hi_time;
00064 static uint32_t oc_lo_time;
00065 // TIM4(TIM8) IC + OverFlow
00066 static uint8_t  tim8p4_ready_flg;
00067 static uint32_t tim8p4_cnt_data;
00068 static uint16_t time_count;
00069 static uint16_t sw_ovrflw_tim8p4;
00070 
00071 //------------------------------------------------------------------------------
00072 //  Frequency Counter
00073 //------------------------------------------------------------------------------
00074 FRQ_CUNTR::FRQ_CUNTR(double ex_clock)
00075 {
00076     // Don't change calling sequence!!
00077     set_external_clock(ex_clock);       // 1st
00078     set_1sec_gate_time();               // 2nd
00079     initialize_Freq_counter();          // 3rd
00080 }
00081 
00082 // Set External Clock Frequency
00083 void FRQ_CUNTR::set_external_clock(double ex_clock)
00084 {
00085     ex_clock_freq = ex_clock;
00086     ex_clk_base  = (uint32_t)(ex_clock_freq * 1000000.0f);       // MHz->Hz
00087     clk_hi_const = (uint32_t)(ex_clock_freq * 1000000.0f * 0.2f);// Count=200mS
00088     // 100ppm error range
00089     uint32_t err = (uint32_t)(ex_clock_freq * 1000000.0f * 0.0001f);
00090     clk_upper_limit = ex_clk_base + err;
00091     clk_lower_limit = ex_clk_base - err;
00092     PRINTF("\r\nSet EXTERNAL Clock mode\r\n");
00093 }
00094 
00095 // Set real gate time
00096 void FRQ_CUNTR::set_1sec_gate_time(void)
00097 {
00098     oc_hi_time = clk_hi_const;              // 200mS
00099     double gt_tmp0 = ex_clk_base * 1.0f;    // one sec
00100     uint32_t gt_tmp1 = (uint32_t)gt_tmp0;
00101     if ((gt_tmp0 - (double)gt_tmp1) >= 0.5f){
00102         ++gt_tmp1;
00103         if ((gt_tmp0 - (double)gt_tmp1) >= 0.5f){
00104             ++gt_tmp1;
00105         }         
00106     }
00107     oc_lo_time = gt_tmp1 - clk_hi_const;
00108 }
00109 
00110 void FRQ_CUNTR::initialize_Freq_counter(void)
00111 {
00112     initialize_TIM2();
00113     initialize_TIM8P4();
00114 }
00115 
00116 // Read new frequency data
00117 double FRQ_CUNTR::read_freq_data(void)
00118 {
00119     return read_freq_w_gate_time(1);
00120 }
00121 
00122 // Read compensated frequency data with suitable gate time
00123 /*
00124     yr: Measured 1PPS
00125     yi: Ideal 1PPS (expected value)
00126     xr: Measued unkown frequency data
00127     --->  xi: Compesated data
00128     comp = (yr-yi)/yi
00129     -> delta = comp * xr
00130     -> xi = xr + delta = compensated data
00131 */
00132 double FRQ_CUNTR::read_compensated_freq_data_w_gt(uint16_t gt)
00133 {
00134     freq_one f_new, f_old;
00135     freq_one one_new, one_old;
00136     uint32_t new_cnt, old_cnt;
00137     uint64_t temp0;
00138     double   temp1,   temp2;
00139 
00140     f_new.f_1sec_dt = fdt_buffer.ring_get_newest_dt();   // newest data
00141     f_old.f_1sec_dt = fdt_buffer.ring_get_pointed_dt(gt);// gt[sec] before data
00142     one_new.f_1sec_dt = onepps_buf.ring_get_newest_dt();
00143     one_old.f_1sec_dt = onepps_buf.ring_get_pointed_dt(gt);
00144     new_cnt = (uint32_t)f_new.t_cnt;
00145     old_cnt = (uint32_t)f_old.t_cnt;    
00146     if (old_cnt > new_cnt){
00147         new_cnt += 0x10000;
00148     }
00149     if ((new_cnt - old_cnt) != gt){
00150         return 0.0f;
00151     }
00152     new_cnt = (uint32_t)one_new.t_cnt;
00153     old_cnt = (uint32_t)one_old.t_cnt;
00154     if (old_cnt > new_cnt){
00155         new_cnt += 0x10000;
00156     }
00157     if ((new_cnt - old_cnt) != gt){
00158         return 0.0f;
00159     }
00160     // comp = (yr-yi)/yi
00161     temp0 = get_diff(one_new.f_1sec_dt, one_old.f_1sec_dt);
00162     temp1 = (double)temp0 - ex_clock_freq * 1000000.0f * (double)gt;   
00163     temp2 = temp1 / (ex_clock_freq * 1000000.0f * (double)gt);
00164     // delta = comp * xr
00165     temp0 = get_diff(f_new.f_1sec_dt, f_old.f_1sec_dt);
00166     temp1 = temp2 * (double)temp0;
00167     // xi = xr + delta
00168     temp2 = (double)temp0 + temp1;
00169     return temp2 / (double)gt;
00170 }
00171 
00172 // Read new frequency data with specific gate time
00173 double FRQ_CUNTR::read_freq_w_gate_time(uint16_t gt)
00174 {
00175     freq_one f_new, f_old;
00176 
00177     if (gt == 0){ return 0.0f;}
00178     f_new.f_1sec_dt = fdt_buffer.ring_get_newest_dt();   // newest data
00179     f_old.f_1sec_dt = fdt_buffer.ring_get_pointed_dt(gt);// gt[sec] before data
00180     uint32_t new_cnt = (uint32_t)f_new.t_cnt;
00181     uint32_t old_cnt = (uint32_t)f_old.t_cnt;
00182     if (old_cnt > new_cnt){
00183         new_cnt += 0x10000;
00184     }
00185     if ((new_cnt - old_cnt) == gt){  // make sure gt[sec]
00186         uint64_t dt = get_diff(f_new.f_1sec_dt, f_old.f_1sec_dt);
00187         return (double)dt / (double)gt;
00188     } else {
00189         return 0.0f;
00190     }
00191 }
00192 
00193 // Read status (new frequency data is available or not)
00194 uint32_t FRQ_CUNTR::status_freq_update(void)
00195 {
00196     return check_ic1_status_TIM8P4();
00197 }
00198 
00199 // Read status (new 1PPS data is available or not)
00200 uint32_t FRQ_CUNTR::status_1pps(void)
00201 {
00202     return check_ic2_status_TIM2();
00203 }
00204 
00205 // Read GPS 1PPS counter value
00206 uint32_t FRQ_CUNTR::calc_1PPS_newest(void)
00207 {
00208     freq_one f_new, f_old;
00209     uint64_t diff = 0;
00210 
00211     f_new.f_1sec_dt = onepps_buf.ring_get_newest_dt();  // newest data
00212     f_old.f_1sec_dt = onepps_buf.ring_get_pointed_dt(1);
00213     uint32_t new_cnt = (uint32_t)f_new.t_cnt;
00214     uint32_t old_cnt = (uint32_t)f_old.t_cnt;
00215     if (old_cnt > new_cnt){
00216         new_cnt += 0x10000;
00217     }
00218     if ((new_cnt - old_cnt) == 1){  // make sure gt[sec]
00219         diff = get_diff(f_new.f_1sec_dt, f_old.f_1sec_dt);
00220     }
00221     if ((diff > clk_upper_limit) || (diff < clk_lower_limit)){
00222         // Missing 1PPS signal or Base clock is out of range
00223         gps_ready = 0;
00224         onepps_buf.ring_clear_buf();    // Clear ring buffer
00225         return 0;
00226     } else {    // GPS 1pps is in good range
00227         gps_ready = 1;
00228         onepps_ready_flg = 0;
00229         onepps_newest = diff;
00230         return diff;
00231     }
00232 }
00233 
00234 // Avarage measured data GPS 1PPS by External Base Clock
00235 double FRQ_CUNTR::read_avarage_1pps(void)
00236 {
00237     freq_one f_new, f_old;
00238     int16_t size = 0;
00239 
00240     f_new.f_1sec_dt = onepps_buf.ring_get_newest_dt();  // newest data
00241     size = onepps_buf.ring_get_buf_size();
00242     if (size >= 1500){      // Not use old 500 data
00243         gate_time = 1000;       // Gate Time = 16min40sec
00244     } else if (size >= 200){// Not use old 100 data
00245         gate_time = 100;        // Gate Time = 1min40sec
00246     } else if (size >= 20){ // Not use old 10 data
00247         gate_time = 10;         // Gate Time = 10sec
00248     } else if (size >= 10){ // Not use old 9 data
00249         gate_time = 1;          // Gate Time = 1sec
00250     } else {
00251         gate_time = 1;
00252         return 0.0f;            // data is not avairable
00253     }
00254     f_old.f_1sec_dt = onepps_buf.ring_get_pointed_dt(gate_time);
00255     uint32_t new_cnt = (uint32_t)f_new.t_cnt;
00256     uint32_t old_cnt = (uint32_t)f_old.t_cnt;
00257     if (old_cnt > new_cnt){
00258         new_cnt += 0x10000;
00259     }
00260     if ((new_cnt - old_cnt) == gate_time){  // make sure gt[sec]
00261         uint64_t dt = get_diff(f_new.f_1sec_dt, f_old.f_1sec_dt);
00262         return (double)dt / (double)gate_time;
00263     } else {
00264         return 0.0f;
00265     }
00266 }
00267 
00268 // Read number of buffered data
00269 uint32_t FRQ_CUNTR::read_num_in_buffer(void)
00270 {
00271     return onepps_buf.ring_get_buf_size();
00272 }
00273 
00274 // Newest measued data GPS 1PPS
00275 uint32_t FRQ_CUNTR::read_newest_1pps(void)
00276 {
00277     calc_1PPS_newest();
00278     return onepps_newest;
00279 }
00280 
00281 // Check GPS condition
00282 uint32_t FRQ_CUNTR::status_gps(void)
00283 {
00284     if (gps_ready){
00285         return gate_time;
00286     } else {
00287         return 0;   // 1PPS signal is not avarable
00288     }
00289 }
00290 
00291 uint64_t FRQ_CUNTR::get_diff(uint64_t new_dt, uint64_t old_dt){
00292     uint64_t nw,od;
00293 
00294     nw = new_dt & 0x0000ffffffffffff;   // select 48bit data
00295     od = old_dt & 0x0000ffffffffffff;
00296     if (nw < od){ // 48bits counter overflow!
00297         nw += 0x0001000000000000;
00298     }
00299     return (nw - od);
00300 }
00301 
00302 //------------------------------------------------------------------------------
00303 //  Frequency Counter / Reciprocal measurement
00304 //------------------------------------------------------------------------------
00305 void FRQ_CUNTR::recipro_start_measure(void)
00306 {
00307     recipro_step = 0;               // initialize step
00308     __disable_irq();
00309     TIM2->SR &= ~TIM_SR_CC4IF;      // clear IC flag
00310     TIM2->DIER |= TIM_DIER_CC4IE;   // Enable IC4
00311     __enable_irq();
00312 }
00313 
00314 uint32_t FRQ_CUNTR::recipro_check_trigger(void)
00315 {
00316     if (recipro_step == 2){         // check IC event happan or not
00317         return 1;                   // happen
00318     } else {
00319         return 0;                   // not yet
00320     }
00321 }
00322 
00323 uint32_t FRQ_CUNTR::recipro_read_data(void)
00324 {
00325     uint64_t dt;
00326     if (recipro_stop < recipro_start){  // 32bit counter overflow
00327         dt =  0x100000000 +  recipro_stop;
00328         dt -=  recipro_stop;
00329     } else {
00330         dt = recipro_stop - recipro_start;
00331     }
00332     return (uint32_t)dt;
00333 }
00334 
00335 //------------------------------------------------------------------------------
00336 //  TIM2 (32bit Counter + IC + OC)
00337 //------------------------------------------------------------------------------
00338 // Read TIM2 captured counter value
00339 uint32_t FRQ_CUNTR::read_ic2_counter_TIM2(void)
00340 {
00341     return tim2_cnt_data;   // return TIM2->CCR2;
00342 }
00343 
00344 // Check TIM2 IC2 status
00345 uint32_t FRQ_CUNTR::check_ic2_status_TIM2(void)
00346 {
00347     if (tim2_ready_flg == 0){
00348         return 0;
00349     } else {                // GPS 1PPS is comming
00350         tim2_ready_flg = 0;
00351         return 1;
00352     }
00353 }
00354 
00355 // Check OC port status
00356 uint8_t FRQ_CUNTR::read_oc_port_status(void)
00357 {
00358     uint32_t p = GPIOB->IDR;
00359     if (p & 0x0400){        // Check PB10 status
00360         return 1;           // H level
00361     } else {
00362         return 0;           // L level
00363     }
00364 }
00365 
00366 //------------------------------------------------------------------------------
00367 //  TIM8+TIM4 (32bit Counter + IC)
00368 //------------------------------------------------------------------------------
00369 // Read TIM8+4(as 32bit) captured counter value
00370 uint32_t FRQ_CUNTR::read_counter_TIM8P4(void)
00371 {
00372     return tim8p4_cnt_data;
00373 }
00374 
00375 // Check TIM8 IC2 & TIM4 IC1 status
00376 uint32_t FRQ_CUNTR::check_ic1_status_TIM8P4(void)
00377 {
00378     if (tim8p4_ready_flg == 0){
00379         return 0;
00380     } else {                // Gate signal is comming
00381         tim8p4_ready_flg = 0;
00382         return 1;
00383     }
00384 }
00385 
00386 //------------------------------------------------------------------------------
00387 //  Initialize TIM2 and TIM8+4
00388 //------------------------------------------------------------------------------
00389 // Initialize TIM2
00390 // External clock(50MHz)->PA_5 and
00391 // IC2->PA_1 for GPS 1pps signal measurement
00392 // IC4->PA_3 for Reciprocal frequency counting mode
00393 // OC3->PB_10 for Base gate time output(1 Second and other gate time)
00394 /*
00395     ????? Strange behavior :
00396             TIM2_ETR is assigned AF2 but following is assigned AF1! 
00397  */
00398 void FRQ_CUNTR::initialize_TIM2(void)
00399 {
00400     // PA5 -> Counter frequency input pin as Timer2 ETR(CH1?)
00401     RCC->AHB1ENR  |= (RCC_AHB1ENR_GPIOAEN);
00402     GPIOA->AFR[0] &= 0xff0fffff;
00403     GPIOA->AFR[0] |= GPIO_AF1_TIM2 << 20;       // 5(PA5) x 4bits = AFSEL5
00404     // ??? AF3(TIM2_ETR) does NOT works!!
00405     //GPIOA->AFR[0] |= ((uint8_t)0x02) << 20;
00406     GPIOA->MODER  &= ~(GPIO_MODER_MODER5);      // AF
00407     GPIOA->MODER  |= GPIO_MODER_MODER5_1;       //  alternate function mode
00408     GPIOA->PUPDR  &= ~(GPIO_PUPDR_PUPDR5);      // PU
00409     GPIOA->PUPDR  |= GPIO_PUPDR_PUPDR5_0;       //  Pull-up mode
00410     // Initialize Timer2(32bit) for an external(ECE bit = 1) up counter mode
00411     RCC->APB1ENR  |= RCC_APB1ENR_TIM2EN;
00412                                 // count_up + div by 1
00413     TIM2->CR1     &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD));
00414                                 // only counter overflow for interrupt
00415     TIM2->CR1     |= (uint16_t)TIM_CR1_URS;
00416                                 // Up counter uses from 0 to max(32bit)
00417     TIM2->ARR      = 0xffffffff;
00418     TIM2->PSC      = 0x0000;                    // 1/1
00419     TIM2->CCER    &= (uint16_t)~TIM_CCER_CC1E;  // Disable the CC1
00420                                 // input filter + input select
00421     TIM2->CCMR1   &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S);
00422     TIM2->CCMR1   |= TIM_CCMR1_CC1S_0;
00423     TIM2->SMCR     =
00424              (TIM_SMCR_ECE| TIM_ETRPRESCALER_DIV1 | TIM_CLOCKSOURCE_ETRMODE1);
00425     TIM2->CR1     |= (uint16_t)TIM_CR1_CEN;     // Enable the TIM Counter
00426     // PA1 -> Input Capture pin as Timer2 IC2
00427     GPIOA->AFR[0] &= 0xffffff0f;
00428     GPIOA->AFR[0] |= GPIO_AF1_TIM2 << 4;        // 1bit x 4
00429     GPIOA->MODER  &= ~(GPIO_MODER_MODER1);      // AF
00430     GPIOA->MODER  |= GPIO_MODER_MODER1_1;       //  alternate function mode  
00431     GPIOA->PUPDR  &= ~(GPIO_PUPDR_PUPDR1);      // PU
00432     GPIOA->PUPDR  |= GPIO_PUPDR_PUPDR1_0;       //  Pull-up mode
00433     // Initialize Timer2 IC2
00434     TIM2->CCER    &= (uint16_t)~TIM_CCER_CC2E;  // Disable the CC2
00435                                 // input filter + input select
00436     TIM2->CCMR1   &= ~(TIM_CCMR1_IC2F | TIM_CCMR1_CC2S);
00437     TIM2->CCMR1   |= TIM_CCMR1_CC2S_0;
00438                                 // positive edge
00439     TIM2->CCER    &= (uint16_t)~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
00440     TIM2->CCER    |= (uint16_t)TIM_CCER_CC2E;   // enable capture
00441     // PA3 -> Input Capture pin as Timer2 IC4 for Reciprocal
00442     GPIOA->AFR[0] &= 0xffff0fff;
00443     GPIOA->AFR[0] |= GPIO_AF1_TIM2 << 12;       // 3bit x 4
00444     GPIOA->MODER  &= ~(GPIO_MODER_MODER3);      // AF
00445     GPIOA->MODER  |= GPIO_MODER_MODER3_1;       //  alternate function mode
00446     GPIOA->PUPDR  &= ~(GPIO_PUPDR_PUPDR3);      // PU
00447     GPIOA->PUPDR  |= GPIO_PUPDR_PUPDR3_0;       //  Pull-up mode
00448     // Initialize Timer2 IC4
00449     TIM2->CCER    &= (uint16_t)~TIM_CCER_CC4E;  // Disable the CC
00450     TIM2->CCMR2   &= ~(TIM_CCMR2_IC4F | TIM_CCMR2_CC4S);
00451     TIM2->CCMR2   |= (TIM_CCMR2_CC4S_0 + TIM_CCMR2_IC4F_1); // filter = fCLK/4
00452                                 // positive edge
00453     TIM2->CCER    &= (uint16_t)~(TIM_CCER_CC4P | TIM_CCER_CC4NP);
00454     TIM2->CCER    |= (uint16_t)TIM_CCER_CC4E;   // enable capture
00455     // PB10 -> Output Compare pin as Timer2 OC3
00456     GPIOB->AFR[1] &= 0xfffff0ff;
00457     GPIOB->AFR[1] |= GPIO_AF1_TIM2 << 8;        // 10bit x 4 -> 2bit x 4(AFR[1])
00458     GPIOB->MODER  &= ~(GPIO_MODER_MODER10);     // AF
00459     GPIOB->MODER  |= GPIO_MODER_MODER10_1;      //  alternate function mode
00460     GPIOB->OTYPER &= ~(GPIO_OTYPER_OT_10);      // Output Push-Pull=0
00461     GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR10;  //  Speed full=11
00462     GPIOB->PUPDR  &= ~(GPIO_PUPDR_PUPDR10);     // No Pull-up&down = 0
00463     // Initialize Timer2 OC3
00464                                 // Reset the CC3E Bit (Disable output)
00465     TIM2->CCER    &= (uint16_t)~TIM_CCER_CC3E;
00466     TIM2->CCMR2   &= ~(TIM_CCMR2_OC3M | TIM_CCMR2_CC3S |
00467                         TIM_CCMR2_OC3PE | TIM_CCMR2_OC3CE | TIM_CCMR2_OC3FE);
00468     TIM2->CCMR2   |= TIM_CCMR2_OC3M_2;          // force to low level
00469                                 // Reset the Output Polarity level (active H)
00470     TIM2->CCER    &= (uint16_t)~TIM_CCER_CC3P;
00471                                 // Set the CC3E Bit (Enable output)
00472     TIM2->CCER    |= (uint16_t)TIM_CCER_CC3E;
00473                                 // Set the Capture Compare Register value
00474     TIM2->CCR3     = TIM2->CNT + oc_lo_time;
00475     // Up counter based on gate time period
00476     time_count_onepps = 0;
00477     // Only for Debug purpose
00478     //  PA
00479     PRINTF("\r\n// Timer2(32bit) for an internal up counter mode\r\n");
00480     PRINTF("// Set GPIO for Timer2\r\n");
00481     PRINTF("// PA1  -> Input Capture pin as Timer2 CH2/TI2\r\n");
00482     PRINTF("// PA3  -> Input Capture pin as Timer2 CH4/TI4\r\n");
00483     PRINTF("GPIOA->AFRL  0x%08x:0x%08x\r\n",&GPIOA->AFR[0], GPIOA->AFR[0]);
00484     PRINTF("GPIOA->AFRH  0x%08x:0x%08x\r\n",&GPIOA->AFR[1], GPIOA->AFR[1]);
00485     PRINTF("GPIOA->MODER 0x%08x:0x%08x\r\n",&GPIOA->MODER, GPIOA->MODER);
00486     PRINTF("GPIOA->PUPDR 0x%08x:0x%08x\r\n",&GPIOA->PUPDR, GPIOA->PUPDR);
00487     //  PB
00488     PRINTF("// PB10 -> Output Compare pin as Timer2 CH3/TI3\r\n");
00489     PRINTF("GPIOB->AFRL  0x%08x:0x%08x\r\n",&GPIOB->AFR[0], GPIOB->AFR[0]);
00490     PRINTF("GPIOB->AFRH  0x%08x:0x%08x\r\n",&GPIOB->AFR[1], GPIOB->AFR[1]);
00491     PRINTF("GPIOB->MODER 0x%08x:0x%08x\r\n",&GPIOB->MODER, GPIOB->MODER);
00492     PRINTF("GPIOB->PUPDR 0x%08x:0x%08x\r\n",&GPIOB->PUPDR, GPIOB->PUPDR);
00493     //  TIM2
00494     PRINTF("// PA1 -> Timer2 IC2\r\n");
00495     PRINTF("// PA3 -> Timer2 IC4\r\n");
00496     PRINTF("// PB10-> Timer2 OC3\r\n");
00497     PRINTF("TIM2->CR1    0x%08x:0x%08x\r\n",&TIM2->CR1, TIM2->CR1);
00498     PRINTF("TIM2->ARR    0x%08x:0x%08x\r\n",&TIM2->ARR, TIM2->ARR);
00499     PRINTF("TIM2->PSC    0x%08x:0x%08x\r\n",&TIM2->PSC, TIM2->PSC);
00500     PRINTF("TIM2->CCMR1  0x%08x:0x%08x\r\n",&TIM2->CCMR1, TIM2->CCMR1);
00501     PRINTF("TIM2->CCMR2  0x%08x:0x%08x\r\n",&TIM2->CCMR2, TIM2->CCMR2);
00502     PRINTF("TIM2->CCER   0x%08x:0x%08x\r\n",&TIM2->CCER, TIM2->CCER);
00503     PRINTF("TIM2->SMCR   0x%08x:0x%08x\r\n",&TIM2->SMCR, TIM2->SMCR);
00504     PRINTF("TIM2->CCR3   0x%08x:0x%08x\r\n",&TIM2->CCR3, TIM2->CCR3);
00505     // Interrupt Timer2 IC2,OC3 & Overflow
00506     tim2_ready_flg = 0;
00507     tim2_cnt_data = 0;
00508     sw_ovrflw_tim2 = 0;
00509     TIM2->SR = 0;           // clear all IC/OC flag
00510     TIM2->DIER = 0;         // Reset all interrupt flag
00511     TIM2->DIER = TIM_DIER_CC2IE + TIM_DIER_CC3IE + TIM_DIER_UIE;
00512     NVIC_SetVector(TIM2_IRQn, (uint32_t)irq_ic2_TIM2);
00513     NVIC_ClearPendingIRQ(TIM2_IRQn);
00514     NVIC_EnableIRQ(TIM2_IRQn);
00515     PRINTF("TIM2->DIER   0x%08x:0x%08x\r\n\r\n",&TIM2->DIER, TIM2->DIER);
00516 }
00517 
00518 // Initialize TIM8 & TIM4 as 32bit counter (TIM8(Low 16bit) + TIM4(High 16bit))
00519 //   TIM8 clock input is unkown freq.(measuring freq.) and TIM4 is slave counter
00520 //   1sec gate signal connected both TIM8 IC2, TIM4 IC1 with TIM2 OC3
00521 void FRQ_CUNTR::initialize_TIM8P4(void)
00522 {
00523     // Timer8 input max freq.= 108MHz (@SystemCoreClock = 216MHz)
00524     // PC6 -> Unkown frequency input pin as Timer8 CH1/TI1
00525     RCC->AHB1ENR  |= (RCC_AHB1ENR_GPIOCEN);
00526     GPIOC->AFR[0] &= 0xf0ffffff;
00527     GPIOC->AFR[0] |= GPIO_AF3_TIM8 << 24;       // 6bit x 4
00528     GPIOC->MODER  &= ~(GPIO_MODER_MODER6);      // AF
00529     GPIOC->MODER  |= GPIO_MODER_MODER6_1;       //  alternate function mode
00530     GPIOC->PUPDR  &= ~(GPIO_PUPDR_PUPDR6);      // PU
00531     GPIOC->PUPDR  |= GPIO_PUPDR_PUPDR6_0;       //  Pull-up mode
00532     // Initialize Timer8(16bit) for an external up counter mode
00533     RCC->APB2ENR  |= RCC_APB2ENR_TIM8EN;
00534                                 // count_up + div by 1
00535     TIM8->CR1     &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD));
00536                                 // update request only by overflow
00537     TIM8->CR1     |= (uint16_t)TIM_CR1_URS;
00538     TIM8->ARR      = 0xffff;                    // Use 16bit full
00539     TIM8->CCER    &= (uint16_t)~TIM_CCER_CC1E;  // Disable the CC1
00540                                 // input filter + input select
00541     TIM8->CCMR1   &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S);
00542     TIM8->CCMR1   |= TIM_CCMR1_CC1S_0;// CC1 channel = TI1
00543                                 // Not use IC1
00544     TIM8->CCER    &= 
00545                    (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NE | TIM_CCER_CC1NP);
00546                                 // external mode 1
00547     TIM8->SMCR    &= ~(TIM_SMCR_ECE | TIM_SMCR_TS | TIM_SMCR_SMS);
00548                                 // ECE must be ZERO!!!!
00549     TIM8->SMCR    |= ( TIM_TS_TI1FP1 | TIM_SLAVEMODE_EXTERNAL1);
00550     TIM8->CR2     &= (uint16_t)~(TIM_CR2_TI1S | TIM_CR2_MMS);
00551     TIM8->CR2     |= (uint16_t)TIM_CR2_MMS_1;   // TRGO update
00552     TIM8->CR1     |= (uint16_t)TIM_CR1_CEN;     // Enable the TIM Counter
00553     // PC7 -> Input Capture pin as Timer8 IC2
00554     GPIOC->AFR[0] &= 0x0fffffff;
00555     GPIOC->AFR[0] |= GPIO_AF3_TIM8 << 28;       // 7bit x 4
00556     GPIOC->MODER  &= ~(GPIO_MODER_MODER7);      // AF
00557     GPIOC->MODER  |= GPIO_MODER_MODER7_1;       //  alternate function mode
00558     GPIOC->PUPDR  &= ~(GPIO_PUPDR_PUPDR7);      // PU
00559     GPIOC->PUPDR  |= GPIO_PUPDR_PUPDR7_0;       //  Pull-up mode
00560     // Initialize Timer8 IC2
00561     TIM8->CCER    &= (uint16_t)~TIM_CCER_CC2E;    // Disable the CC2
00562                                 // input filter + input select
00563     TIM8->CCMR1   &= ~(TIM_CCMR1_IC2F | TIM_CCMR1_CC2S);
00564     TIM8->CCMR1   |= TIM_CCMR1_CC2S_0;
00565                                 // positive edge
00566     TIM8->CCER    &= (uint16_t)~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
00567     TIM8->CCER    |= (uint16_t)TIM_CCER_CC2E;     // enable capture
00568     // Initialize Timer4(16bit) as slave counter of TIM8
00569     // TIM8 overflow event -> ITR3 as Timer4 clock
00570     RCC->APB1ENR  |= RCC_APB1ENR_TIM4EN;
00571     TIM4->CR1     &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD));
00572                                 // only counter overflow for interrupt
00573     TIM4->CR1     |= (uint16_t)TIM_CR1_URS;
00574                                 // Up counter uses from 0 to max(32bit)
00575     TIM4->ARR      = 0xffff;                    // Use 16bit full
00576     TIM4->CCER    &= (uint16_t)~TIM_CCER_CC1E;  // Disable the CC1
00577                                 // input filter + input select
00578     TIM4->CCMR1   &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S);
00579     TIM4->CCMR1   |= TIM_CCMR1_CC1S_0;          // CC1 channel = TI1
00580                                 // Not use IC1
00581     TIM4->CCER    &= 
00582                    (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NE | TIM_CCER_CC1NP);
00583                                 // external mode 1
00584     TIM4->SMCR    &= ~(TIM_SMCR_ECE | TIM_SMCR_TS | TIM_SMCR_SMS);
00585     TIM4->SMCR    |= (TIM_TS_ITR3);             // Set Internal Triger 3 (ITR3)
00586     TIM4->SMCR    |= (TIM_SLAVEMODE_EXTERNAL1); // ECE must be ZERO!!!!
00587     TIM4->CR2     &= (uint16_t)~(TIM_CR2_TI1S | TIM_CR2_MMS);
00588     TIM4->CR2     |= (uint16_t)TIM_CR2_MMS_1;   // TRGO update
00589     TIM4->CR1     |= (uint16_t)TIM_CR1_CEN;     // Enable the TIM Counter
00590     // PB6 -> Input Capture pin as Timer4 IC1
00591     GPIOB->AFR[0] &= 0xf0ffffff;
00592     GPIOB->AFR[0] |= GPIO_AF2_TIM4 << 24;       // 6bit x 4
00593     GPIOB->MODER  &= ~(GPIO_MODER_MODER6);      // AF
00594     GPIOB->MODER  |= GPIO_MODER_MODER6_1;       //  alternate function mode
00595     GPIOB->PUPDR  &= ~(GPIO_PUPDR_PUPDR6);      // PU
00596     GPIOB->PUPDR  |= GPIO_PUPDR_PUPDR6_0;       //  Pull-up mode
00597     // Initialize Timer4 IC1
00598     TIM4->CCER    &= (uint16_t)~TIM_CCER_CC1E;
00599     TIM4->CCMR1   &= ~(TIM_CCMR1_CC1S | TIM_CCMR1_IC1F);
00600     TIM4->CCMR1   |= TIM_CCMR1_CC1S_0;
00601                                 // positive edge
00602     TIM4->CCER    &= (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
00603     TIM4->CCER    |= (uint16_t)TIM_CCER_CC1E;   // enable capture
00604     // Up counter based on gate time period
00605     time_count = 0;
00606     // Only for Debug purpose
00607     PRINTF("\r\n// Timer8(16bit high(max106MHz) clock)\r\n");
00608     PRINTF("//  and Timer4(16bit low clock) combined up counter\r\n");
00609     PRINTF("// Set GPIO for Timer8&4\r\n");
00610     //  PB
00611     PRINTF("// PB6 -> Input Capture pin as Timer4 CH1/TI1\r\n");
00612     PRINTF("GPIOB->AFRL    0x%08x:0x%08x\r\n",&GPIOB->AFR[0], GPIOB->AFR[0]);
00613     PRINTF("GPIOB->AFRH    0x%08x:0x%08x\r\n",&GPIOB->AFR[1], GPIOB->AFR[1]);
00614     PRINTF("GPIOB->MODER   0x%08x:0x%08x\r\n",&GPIOB->MODER, GPIOB->MODER);
00615     PRINTF("GPIOB->PUPDR   0x%08x:0x%08x\r\n",&GPIOB->PUPDR, GPIOB->PUPDR);
00616     PRINTF("GPIOB->OTYPER  0x%08x:0x%08x\r\n",&GPIOB->OTYPER, GPIOB->OTYPER);
00617     PRINTF("GPIOB->OSPEEDR 0x%08x:0x%08x\r\n",&GPIOB->OSPEEDR, GPIOB->OSPEEDR);
00618     //  PC
00619     PRINTF("// PC6 -> unkown frequency input pin as Timer8 CH1/TI1\r\n");
00620     PRINTF("// PC7 -> Input Capture pin as Timer8 CH2/TI2\r\n");
00621     PRINTF("GPIOC->AFRL    0x%08x:0x%08x\r\n",&GPIOC->AFR[0], GPIOC->AFR[0]);
00622     PRINTF("GPIOC->AFRH    0x%08x:0x%08x\r\n",&GPIOC->AFR[1], GPIOC->AFR[1]);
00623     PRINTF("GPIOC->MODER   0x%08x:0x%08x\r\n",&GPIOC->MODER, GPIOC->MODER);
00624     PRINTF("GPIOC->PUPDR   0x%08x:0x%08x\r\n",&GPIOC->PUPDR, GPIOC->PUPDR);
00625     PRINTF("GPIOC->OTYPER  0x%08x:0x%08x\r\n",&GPIOC->OTYPER, GPIOC->OTYPER);
00626     PRINTF("GPIOC->OSPEEDR 0x%08x:0x%08x\r\n",&GPIOC->OSPEEDR, GPIOC->OSPEEDR);
00627     //  TIM8
00628     PRINTF("// PC6 -> Timer8(16bit) for an external up counter mode\r\n");
00629     PRINTF("// PC7 -> Timer8 IC2\r\n");
00630     PRINTF("TIM8->CR1      0x%08x:0x%08x\r\n",&TIM8->CR1, TIM8->CR1);
00631     PRINTF("TIM8->CR2      0x%08x:0x%08x\r\n",&TIM8->CR2, TIM8->CR2);
00632     PRINTF("TIM8->ARR      0x%08x:0x%08x\r\n",&TIM8->ARR, TIM8->ARR);
00633     PRINTF("TIM8->PSC      0x%08x:0x%08x\r\n",&TIM8->PSC, TIM8->PSC);
00634     PRINTF("TIM8->CCMR1    0x%08x:0x%08x\r\n",&TIM8->CCMR1, TIM8->CCMR1);
00635     PRINTF("TIM8->CCMR2    0x%08x:0x%08x\r\n",&TIM8->CCMR2, TIM8->CCMR2);
00636     PRINTF("TIM8->CCER     0x%08x:0x%08x\r\n",&TIM8->CCER, TIM8->CCER);
00637     PRINTF("TIM8->SMCR     0x%08x:0x%08x\r\n",&TIM8->SMCR, TIM8->SMCR);
00638     //  TIM4
00639     PRINTF("// PB6 -> Timer4 IC1\r\n");
00640     PRINTF("TIM4->CR1      0x%08x:0x%08x\r\n",&TIM4->CR1, TIM4->CR1);
00641     PRINTF("TIM4->ARR      0x%08x:0x%08x\r\n",&TIM4->ARR, TIM4->ARR);
00642     PRINTF("TIM4->PSC      0x%08x:0x%08x\r\n",&TIM4->PSC, TIM4->PSC);
00643     PRINTF("TIM4->CCMR1    0x%08x:0x%08x\r\n",&TIM4->CCMR1, TIM4->CCMR1);
00644     PRINTF("TIM4->CCMR2    0x%08x:0x%08x\r\n",&TIM4->CCMR2, TIM4->CCMR2);
00645     PRINTF("TIM4->CCER     0x%08x:0x%08x\r\n",&TIM4->CCER, TIM4->CCER);
00646     PRINTF("TIM4->SMCR     0x%08x:0x%08x\r\n",&TIM4->SMCR, TIM4->SMCR);
00647     // Interrupt Timer4 IC1 (NOT Timer8 IC2) & Overflow
00648     tim8p4_ready_flg = 0;
00649     tim8p4_cnt_data = 0;
00650     sw_ovrflw_tim8p4 = 0;
00651     TIM8->SR = 0;           // clear all IC/OC flag
00652     TIM4->SR = 0;           // clear all IC/OC flag
00653     TIM4->DIER = 0;         // Reset all interrupt flag
00654     TIM4->DIER = TIM_DIER_CC1IE + TIM_DIER_UIE;
00655     NVIC_SetVector(TIM4_IRQn, (uint32_t)irq_ic1_TIM8P4);
00656     NVIC_ClearPendingIRQ(TIM4_IRQn);
00657     NVIC_EnableIRQ(TIM4_IRQn);
00658     PRINTF("TIM4->DIER     0x%08x:0x%08x\r\n\r\n",&TIM4->DIER, TIM4->DIER);
00659     PRINTF("RCC->APB1ENR   0x%08x:0x%08x\r\n\r\n",&RCC->APB1ENR, RCC->APB1ENR);
00660 }
00661 
00662 //------------------------------------------------------------------------------
00663 //  Frequency check for test & debug purpose
00664 //------------------------------------------------------------------------------
00665 // Read TIM2 Clock frequency
00666 uint32_t FRQ_CUNTR::read_base_clock_frequency(double gatetime)
00667 {
00668     TIM2->CNT = 0;
00669     wait(gatetime);                         // Gate time for count
00670     uint32_t freq = TIM2->CNT;              // read counter
00671     PRINTF("Clock freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq, gatetime);
00672     return freq;                            // return counter data
00673 }
00674 
00675 // Read TIM8(+TIM4) Input frequency
00676 uint32_t FRQ_CUNTR::read_input_frequency(double gatetime)
00677 {
00678     TIM8->CR1 &= ~(uint16_t)TIM_CR1_CEN;    // disable the TIM8 Counter
00679     TIM4->CNT  = 0;
00680     TIM8->CNT  = 0;
00681     TIM8->CR1 |= (uint16_t)TIM_CR1_CEN;     // Enable the TIM8 Counter
00682     wait(gatetime);                // Gate time for count
00683     TIM8->CR1 &= ~(uint16_t)TIM_CR1_CEN;    // disable the TIM8 Counter
00684     uint32_t freq = (TIM4->CNT << 16) + TIM8->CNT;
00685     TIM8->CR1 |= (uint16_t)TIM_CR1_CEN;     // Enable the TIM8 Counter
00686     PRINTF("Input freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq, gatetime);
00687     return freq;                            // read counter
00688 }
00689 
00690 void FRQ_CUNTR::debug_printf_all_buffer(void)
00691 {
00692     fdt_buffer.debug_print_all_buffer();
00693 }
00694 
00695 void FRQ_CUNTR::debug_printf_internal_data(void)
00696 {
00697     printf("Debug information\r\n");
00698     printf("ex_clock_freq    %f\r\n", ex_clock_freq);
00699     printf("ex_clk_base     %9d\r\n", ex_clk_base);
00700     printf("clk_hi_const    %9d\r\n", clk_hi_const);
00701     printf("clk_upper_limit %9d\r\n", clk_upper_limit);
00702     printf("clk_lower_limit %9d\r\n", clk_lower_limit);
00703     printf("oc_hi_time      %9d\r\n", oc_hi_time);
00704     printf("oc_lo_time      %9d\r\n", oc_lo_time);
00705     printf("\r\n");
00706 }
00707 
00708 //------------------------------------------------------------------------------
00709 //  Interrupt Handlers
00710 //------------------------------------------------------------------------------
00711 void irq_ic2_TIM2(void)
00712 {
00713     // IC2 (By GPS 1PPS)
00714     if (TIM2->SR & TIM_SR_CC2IF){
00715         TIM2->SR &= ~TIM_SR_CC2IF;  // clear IC flag
00716         tim2_cnt_data = TIM2->CCR2;
00717         tim2_ready_flg = 1;
00718         // data saves intto the ring buffer
00719         onepps_dt.freq_dt = tim2_cnt_data;
00720         onepps_dt.f_sw_dt = sw_ovrflw_tim2;
00721         onepps_dt.t_cnt   = ++time_count_onepps;
00722         onepps_buf.ring_put_dt(onepps_dt.f_1sec_dt);
00723         #if ACTIVE_LED
00724         irq_led3 = !irq_led3;
00725         #endif // ACTIVE_LED
00726     }
00727     // Gate signal (every 1Sec)
00728     if (TIM2->SR & TIM_SR_CC3IF){   // Output Compare
00729         TIM2->SR &= ~TIM_SR_CC3IF;  // clear OC flag
00730         TIM2->CCMR2   &= ~(TIM_CCMR2_OC3M);     // Clear OC mode
00731         // Check PB10 status
00732         if (GPIOB->IDR & 0x0400){   // High level
00733             TIM2->CCR3 = TIM2->CCR3 + oc_hi_time;
00734             TIM2->CCMR2   |= TIM_CCMR2_OC3M_1;  // to be low
00735             #if ACTIVE_LED
00736             irq_led2 = 1;
00737             #endif // ACTIVE_LED
00738         } else {                    // Low level
00739             TIM2->CCR3 = TIM2->CCR3 + oc_lo_time;
00740             TIM2->CCMR2   |= TIM_CCMR2_OC3M_0;  // to be high
00741             #if ACTIVE_LED
00742             irq_led2 = 0;
00743             #endif // ACTIVE_LED
00744         }
00745     }
00746     // IC4 (for reciprocal measurement)
00747     if (TIM2->SR & TIM_SR_CC4IF){
00748         TIM2->SR &= ~TIM_SR_CC4IF;  // clear IC flag
00749         uint32_t data = TIM2->CCR4;
00750         if (recipro_step == 0){
00751             recipro_start = data;
00752             recipro_step = 1;
00753         } else if (recipro_step == 1){
00754             TIM2->DIER &= ~TIM_DIER_CC4IE;  // disable IC4 interrupt
00755             recipro_stop = data;
00756             recipro_step = 2;
00757         }
00758     }
00759     // TIM2 overflow
00760     if (TIM2->SR & TIM_SR_UIF){
00761         TIM2->SR &= ~TIM_SR_UIF;
00762         ++sw_ovrflw_tim2;
00763     }
00764 }
00765 
00766 // TIM4 IC1 Interrupt control (same signal connected to TIM8 IC2)
00767 void irq_ic1_TIM8P4(void)
00768 {
00769     // IC1 (TIM2 Gate signal)
00770     if (TIM4->SR & TIM_SR_CC1IF){
00771         TIM8->SR &= ~TIM_SR_CC2IF;      // clear IC flag
00772         TIM4->SR &= ~TIM_SR_CC1IF;
00773         tim8p4_cnt_data = (TIM4->CCR1 << 16) + TIM8->CCR2;
00774         tim8p4_ready_flg = 1;
00775         // data saves intto the ring buffer
00776         fdt.freq_dt = tim8p4_cnt_data;
00777         fdt.f_sw_dt = sw_ovrflw_tim8p4;
00778         fdt.t_cnt   = ++time_count;
00779         fdt_buffer.ring_put_dt(fdt.f_1sec_dt);
00780         #if ACTIVE_LED
00781         irq_led1 = !irq_led1;
00782         #endif // ACTIVE_LED
00783     }
00784     // TIM4 overflow
00785     if (TIM4->SR & TIM_SR_UIF){
00786         TIM4->SR &= ~TIM_SR_UIF;
00787         ++sw_ovrflw_tim8p4;
00788     }
00789 }
00790 
00791 }   // Frequency_counter
00792 
00793 
00794 
00795