Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: FreqCntr_GPS1PPS_F746F4xx_w_recipro Freq_Cntr_GPS1PPS_F746NG_GUI
Fork of Frq_cuntr_full by
Revision 5:783b039f9119, committed 2016-11-16
- Comitter:
- kenjiArai
- Date:
- Wed Nov 16 13:13:09 2016 +0000
- Parent:
- 4:9d3b3f0a3882
- Child:
- 6:be7123d400ae
- Commit message:
- Frequency counter library only for F746, F411 and F446. Use GPS 1PPS signal for Timer input capture.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RingBuff.lib Wed Nov 16 13:13:09 2016 +0000 @@ -0,0 +1,1 @@ +RingBuff#e206b41f0032
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/fc_GPS1PPS.h Wed Nov 16 13:13:09 2016 +0000
@@ -0,0 +1,205 @@
+/*
+ * mbed Library / Frequency Counter using GPS 1PPS gate pulse
+ * Frequency Counter program
+ * 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.
+ */
+
+/*
+--------------------------------------------------------------------------------
+********* Frequency Counter Functions *********
+Mesurement frequency: 1Hz to 100MHz
+Extended range: Up to 1GHz (1/10 prescaler) or more over (1/20)
+Gate time: 1 sec to 4095sec (extend to more if RAM is avairable)
+1 PPS: GPS receiver(u-blux7/NEO-7) with an external antenna
+Additional function: Reciprocal measurement (less tha 10KHz)
+
+********* Hardware Configration (Board is only ST DISCO-F746NG) *********
+frequency input: PC_6(D1) & PB10(No assign to connector!)
+GPS 1PPS: PA_15(D9), PB_8(D15) & PC_7(D0)
+
+********* Hardware Configration (Board is only ST Nucleo-F411RE) *********
+RESTRICTION -> Max input freqency is 48MHz due to system clock limitation
+frequency input: PA_8(D7) & PA_0(A0)
+GPS 1PPS: PA_9(D8), PB_0(A3) & PA_1(A1)
+--------------------------------------------------------------------------------
+*/
+
+#ifndef MBED_FRQ_CUNTR
+#define MBED_FRQ_CUNTR
+
+#include "mbed.h"
+
+#define DEBUG 0 // use Communication with PC(UART)
+
+typedef union
+{
+ struct {
+ uint64_t f_1sec_dt;
+ };
+ struct {
+ uint32_t freq_dt;
+ uint16_t f_sw_dt;
+ uint16_t t_cnt;
+ };
+} freq_one;
+
+namespace Frequency_counter
+{
+
+/** Frequency Counter program
+ * Only for ST DISCO-F746NG Board(Nucleo-F411RE & F446RE also)
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "fc_GPS1PPS.h"
+ *
+ * using namespace Frequency_counter;
+ *
+ * //----F746---- max input f=100MHz
+ * // frequency input -> PC_6 & PA15(for reciprocal)
+ * // GPS 1PPS -> PB_8,PC_7 & PB_10(for reciprocal)
+ * //----F411---- max input f=48MHz
+ * //----F446---- max input f=90MHz
+ * // frequency input -> PA_8 & PA_0(for reciprocal)
+ * // GPS 1PPS -> PA_9, PB_0 & PA_1(for reciprocal)
+ *
+ * FRQ_CUNTR fc;
+ *
+ * int main() {
+ * double frequency = 0;
+ * while(true) {
+ * while (fc.status_freq_update() == 0) {;}
+ * frequency = fc.read_freq_data(); // 1sec gate
+ * printf("FREQ. = %11.1f\r\n", frequency);
+ * }
+ * }
+ * @endcode
+ */
+
+class FRQ_CUNTR
+{
+
+public:
+
+ /** Configure counter
+ * @param none
+ */
+ FRQ_CUNTR(void);
+
+ /** Read new frequency data (gate time = 1sec)
+ * @param none
+ * @return frequency data
+ */
+ double read_freq_data(void);
+
+ /** Read new frequency data with specific gate time
+ * @param gate time [sec] (1 sec to over 1 hour(F746) or 17 minutes)
+ * @return frequency data
+ */
+ double read_freq_w_gate_time(uint16_t 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);
+
+ /** Reset buffered data
+ * @param none
+ * @return none
+ */
+ void reset_buffered_data(void);
+
+ /** Reciprocal measurement (Step1)
+ * preparation for Reciprocal measurement
+ * @param none
+ * @return none
+ */
+ void recipro_start_measure(void);
+
+ /** Reciprocal measurement (Step2)
+ * check frequency input as IC trigger
+ * @param none
+ * @return 1: done, 0: not yet
+ */
+ uint32_t recipro_check_trigger(void);
+
+ /** Reciprocal measurement (Step3)
+ * read period data
+ * @param none
+ * @return frequency data
+ */
+ uint32_t recipro_read_data(void);
+
+ /** Reciprocal measurement (Step4)
+ * read period data
+ * @param gate time [sec] (1 sec to over 1 hour)
+ * @return time base clock frequency data
+ */
+ uint32_t recipro_base_clk_data(uint16_t gt);
+
+ /** "DEBUG PURPOSE" function
+ * Check input frequency on TIM8+4 or TIM1+3
+ * print internal data (need to define "DEBUG")
+ * @param gate time e.g. 1sec = 1.0f
+ * @return frequency data
+ */
+ uint32_t debug_read_input_frequency(double gatetime);
+
+ /** "DEBUG PURPOSE" function
+ * Check input frequency on TIM2
+ * print internal data (need to define "DEBUG")
+ * @param gate time e.g. 1sec = 1.0f
+ * @return frequency data
+ */
+ uint32_t debug_read_base_clock_frequency(double gatetime);
+
+ /** "DEBUG PURPOSE" function
+ * print internal data (No need to define "DEBUG")
+ * @param none
+ * @return none (just print tha data)
+ */
+ void debug_printf_all_buffer(void);
+
+protected:
+ void start_action(void); // Start trigger for reciprocal
+ void initialize_TIMxPy(void); // Initialize Timer_x + _y (16+16bit)
+ void initialize_TIMz(void); // Initialize Timer_z (32bit)
+ uint64_t get_diff(uint64_t new_dt, uint64_t old_dt);
+
+private:
+ double newest_frequency;
+
+};
+
+/*
+ Interrupt handler does NOT work following code
+ NVIC_SetVector(TIM4_IRQn, (uint32_t)FRQ_CUNTR::irq_ic_TIMxPy);
+ From this reason, I wrote below code and set interrupt handler
+ out side "FRQ_CUNTR" class
+ NVIC_SetVector(TIM4_IRQn, (uint32_t)irq_ic_TIMxPy);
+ */
+ void irq_ic_TIMxPy(void); // TIM4(F746) or TIM3(F411) IC Interrupt
+ void irq_ic_TIMz(void); // TIM2(F746 & F411) IC Interrupt
+
+} // Frequency_counter
+
+#endif // MBED_FRQ_CUNTR
--- /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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/fc_hw_f411.h Wed Nov 16 13:13:09 2016 +0000
@@ -0,0 +1,355 @@
+/*
+ * mbed Library / Frequency Counter using GPS 1PPS gate pulse
+ * Frequency Counter Hardware relataed program
+ * Only for ST Nucleo-F411RE+F446RE
+ *
+ * Re-started: October 5th, 2016 Change board -> DISCO-F746NG
+ * Re-started: October 17th, 2016 Back to F411
+ * Revised: November 8th, 2016
+ *
+ */
+
+#if defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F446RE)
+
+// Following ring buffers are very big!! 1024 x 8(bytes) x 2(buff) = 16KB
+RingBuff<uint64_t> fdt_buffer(1024); // RinBuffer for TIM1+3
+freq_one fdt; // frequency data in pack (interrupt)
+RingBuff<uint64_t> onepps_buf(1024); // RinBuffer for TIM2
+freq_one onepps_dt; // frequency data in pack (interrupt)
+
+//------------------------------------------------------------------------------
+// Initialize TIM1+3 and TIM2
+//------------------------------------------------------------------------------
+// Initialize TIM1 & TIM3 as 32bit counter (TIM1(Low 16bit) + TIM3(High 16bit))
+// TIM1 clock input is unkown freq.(measuring freq.) and TIM3 is slave counter
+// 1PPS gate signal connected both TIM1 IC2, TIM3 IC3 (& TIM2 IC2)
+void FRQ_CUNTR::initialize_TIMxPy(void)
+{
+ // Timer1 input max freq.= 48MHz (@SystemCoreClock = 96MHz)
+ // PA8 -> Unkown frequency input pin as Timer1 CH1/TI1
+ RCC->AHB1ENR |= (RCC_AHB1ENR_GPIOAEN);
+ GPIOA->AFR[1] &= 0xfffffff0;
+ GPIOA->AFR[1] |= GPIO_AF1_TIM1 << 0; // (8-8)bit x 4
+ GPIOA->MODER &= ~(GPIO_MODER_MODER8); // AF
+ GPIOA->MODER |= GPIO_MODER_MODER8_1; // alternate function mode
+ GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR8); // PU
+ GPIOA->PUPDR |= GPIO_PUPDR_PUPDR8_0; // Pull-up mode
+ // Initialize Timer1(16bit) for an external up counter mode
+ RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
+ // count_up + div by 1
+ TIM1->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD));
+ // update request only by overflow
+ TIM1->CR1 |= (uint16_t)TIM_CR1_URS;
+ TIM1->ARR = 0xffff; // Use 16bit full
+ TIM1->CCER = 0; // Reset all
+ // input filter + input select
+ TIM1->CCMR1 &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S);
+ TIM1->CCMR1 |= TIM_CCMR1_CC1S_0; // CC1 channel = TI1
+ // external mode 1
+ TIM1->SMCR &= ~(TIM_SMCR_ECE | TIM_SMCR_TS | TIM_SMCR_SMS);
+ // ECE must be ZERO!!!!
+ TIM1->SMCR |= ( TIM_TS_TI1FP1 | TIM_SLAVEMODE_EXTERNAL1);
+ TIM1->CR2 &= (uint16_t)~(TIM_CR2_TI1S | TIM_CR2_MMS);
+ TIM1->CR2 |= (uint16_t)TIM_CR2_MMS_1; // TRGO update
+ TIM1->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter
+ // PA9 -> Input Capture pin as Timer1 IC2
+ GPIOA->AFR[1] &= 0xffffff0f;
+ GPIOA->AFR[1] |= GPIO_AF1_TIM1 << 4; // (9-8)bit x 4
+ GPIOA->MODER &= ~(GPIO_MODER_MODER9); // AF
+ GPIOA->MODER |= GPIO_MODER_MODER9_1; // alternate function mode
+ GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR9); // PU
+ GPIOA->PUPDR |= GPIO_PUPDR_PUPDR9_0; // Pull-up mode
+ // Initialize Timer1 IC2
+ TIM1->CCER &= (uint16_t)~TIM_CCER_CC2E; // Disable the CC2
+ // input filter + input select
+ TIM1->CCMR1 &= ~(TIM_CCMR1_IC2F | TIM_CCMR1_CC2S);
+ TIM1->CCMR1 |= TIM_CCMR1_CC2S_0;
+ // positive edge
+ TIM1->CCER &= (uint16_t)~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
+ TIM1->CCER |= (uint16_t)TIM_CCER_CC2E; // enable capture
+ // Initialize Timer3(16bit) as slave counter of TIM1
+ // TIM1 overflow event -> ITR0 as Timer3 clock
+ RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
+ TIM3->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD));
+ // only counter overflow for interrupt
+ TIM3->CR1 |= (uint16_t)TIM_CR1_URS;
+ // Up counter uses from 0 to max(32bit)
+ TIM3->ARR = 0xffff; // Use 16bit full
+ TIM3->CCER = 0; // Reset all
+ // external mode 1
+ TIM3->SMCR &= ~(TIM_SMCR_ECE | TIM_SMCR_TS | TIM_SMCR_SMS);
+ TIM3->SMCR |= (TIM_TS_ITR0); // Set Internal Triger 0 (ITR0)
+ TIM3->SMCR |= (TIM_SLAVEMODE_EXTERNAL1); // ECE must be ZERO!!!!
+ TIM3->CR2 &= (uint16_t)~(TIM_CR2_TI1S | TIM_CR2_MMS);
+ TIM3->CR2 |= (uint16_t)TIM_CR2_MMS_1; // TRGO update
+ TIM3->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter
+ // PB0 -> Input Capture pin as Timer3 IC3
+ GPIOB->AFR[0] &= 0xfffffff0;
+ GPIOB->AFR[0] |= GPIO_AF2_TIM3 << 0; // 0bit x 4
+ GPIOB->MODER &= ~(GPIO_MODER_MODER0); // AF
+ GPIOB->MODER |= GPIO_MODER_MODER0_1; // alternate function mode
+ GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPDR0); // PU
+ GPIOB->PUPDR |= GPIO_PUPDR_PUPDR0_0; // Pull-up mode
+ // Initialize Timer3 IC3
+ TIM3->CCER &= (uint16_t)~TIM_CCER_CC2E;
+ TIM3->CCMR2 &= ~(TIM_CCMR2_CC3S | TIM_CCMR2_IC3F);
+ TIM3->CCMR2 |= TIM_CCMR2_CC3S_0;
+ // positive edge
+ TIM3->CCER &= (uint16_t)~(TIM_CCER_CC3P | TIM_CCER_CC3NP);
+ TIM3->CCER |= (uint16_t)TIM_CCER_CC3E; // enable capture
+ // Up counter based on gate time period
+ time_count = 0;
+ // Only for Debug purpose
+ PRINTF("\r\n// Timer1(16bit high(max48MHz) clock)\r\n");
+ PRINTF("// and Timer3(16bit low clock) combined up counter\r\n");
+ PRINTF("// Set GPIO for Timer1&3\r\n");
+ // PA
+ PRINTF("// PA8 -> unkown frequency input pin as Timer1 CH1/TI1\r\n");
+ PRINTF("// PA9 -> Input Capture pin as Timer1 CH2/TI2\r\n");
+ PRINTF("GPIOA->AFRL 0x%08x:0x%08x\r\n",&GPIOA->AFR[0], GPIOA->AFR[0]);
+ PRINTF("GPIOA->AFRH 0x%08x:0x%08x\r\n",&GPIOA->AFR[1], GPIOA->AFR[1]);
+ PRINTF("GPIOA->MODER 0x%08x:0x%08x\r\n",&GPIOA->MODER, GPIOA->MODER);
+ PRINTF("GPIOA->PUPDR 0x%08x:0x%08x\r\n",&GPIOA->PUPDR, GPIOA->PUPDR);
+ PRINTF("GPIOA->OTYPER 0x%08x:0x%08x\r\n",&GPIOA->OTYPER, GPIOA->OTYPER);
+ PRINTF("GPIOA->OSPEEDR 0x%08x:0x%08x\r\n",&GPIOA->OSPEEDR, GPIOA->OSPEEDR);
+ // PB
+ PRINTF("// PB0 -> Input Capture pin as Timer3 CH3/TI3\r\n");
+ PRINTF("GPIOB->AFRL 0x%08x:0x%08x\r\n",&GPIOB->AFR[0], GPIOB->AFR[0]);
+ PRINTF("GPIOB->AFRH 0x%08x:0x%08x\r\n",&GPIOB->AFR[1], GPIOB->AFR[1]);
+ PRINTF("GPIOB->MODER 0x%08x:0x%08x\r\n",&GPIOB->MODER, GPIOB->MODER);
+ PRINTF("GPIOB->PUPDR 0x%08x:0x%08x\r\n",&GPIOB->PUPDR, GPIOB->PUPDR);
+ PRINTF("GPIOB->OTYPER 0x%08x:0x%08x\r\n",&GPIOB->OTYPER, GPIOB->OTYPER);
+ PRINTF("GPIOB->OSPEEDR 0x%08x:0x%08x\r\n",&GPIOB->OSPEEDR, GPIOB->OSPEEDR);
+ // TIM1
+ PRINTF("// PA8 -> Timer1(16bit) for an external up counter mode\r\n");
+ PRINTF("// PA9 -> Timer1 IC2\r\n");
+ PRINTF("TIM1->CR1 0x%08x:0x%08x\r\n",&TIM1->CR1, TIM1->CR1);
+ PRINTF("TIM1->CR2 0x%08x:0x%08x\r\n",&TIM1->CR2, TIM1->CR2);
+ PRINTF("TIM1->ARR 0x%08x:0x%08x\r\n",&TIM1->ARR, TIM1->ARR);
+ PRINTF("TIM1->PSC 0x%08x:0x%08x\r\n",&TIM1->PSC, TIM1->PSC);
+ PRINTF("TIM1->CCMR1 0x%08x:0x%08x\r\n",&TIM1->CCMR1, TIM1->CCMR1);
+ PRINTF("TIM1->CCMR2 0x%08x:0x%08x\r\n",&TIM1->CCMR2, TIM1->CCMR2);
+ PRINTF("TIM1->CCER 0x%08x:0x%08x\r\n",&TIM1->CCER, TIM1->CCER);
+ PRINTF("TIM1->SMCR 0x%08x:0x%08x\r\n",&TIM1->SMCR, TIM1->SMCR);
+ PRINTF("TIM1->DIER 0x%08x:0x%08x\r\n",&TIM1->DIER, TIM1->DIER);
+ // TIM3
+ PRINTF("// PB0 -> Timer3 IC3\r\n");
+ PRINTF("TIM3->CR1 0x%08x:0x%08x\r\n",&TIM3->CR1, TIM3->CR1);
+ PRINTF("TIM3->CR2 0x%08x:0x%08x\r\n",&TIM3->CR2, TIM3->CR2);
+ PRINTF("TIM3->ARR 0x%08x:0x%08x\r\n",&TIM3->ARR, TIM3->ARR);
+ PRINTF("TIM3->PSC 0x%08x:0x%08x\r\n",&TIM3->PSC, TIM3->PSC);
+ PRINTF("TIM3->CCMR1 0x%08x:0x%08x\r\n",&TIM3->CCMR1, TIM3->CCMR1);
+ PRINTF("TIM3->CCMR2 0x%08x:0x%08x\r\n",&TIM3->CCMR2, TIM3->CCMR2);
+ PRINTF("TIM3->CCER 0x%08x:0x%08x\r\n",&TIM3->CCER, TIM3->CCER);
+ PRINTF("TIM3->SMCR 0x%08x:0x%08x\r\n",&TIM3->SMCR, TIM3->SMCR);
+ // Interrupt Timer3 IC3 (NOT Timer1 IC2) & Overflow
+ timxpy_ready_flg = 0;
+ timxpy_cnt_data = 0;
+ sw_ovrflw_timxpy = 0;
+ TIM1->SR = 0; // clear all IC/OC flag
+ TIM3->SR = 0; // clear all IC/OC flag
+ TIM3->DIER = 0; // Reset all interrupt flag
+ TIM3->DIER = TIM_DIER_CC3IE + TIM_DIER_UIE;
+ NVIC_SetVector(TIM3_IRQn, (uint32_t)irq_ic_TIMxPy);
+ NVIC_ClearPendingIRQ(TIM3_IRQn);
+ NVIC_EnableIRQ(TIM3_IRQn);
+ PRINTF("TIM3->DIER 0x%08x:0x%08x\r\n\r\n",&TIM3->DIER, TIM3->DIER);
+ PRINTF("RCC->APB1ENR 0x%08x:0x%08x\r\n\r\n",&RCC->APB1ENR, RCC->APB1ENR);
+}
+
+// Initialize TIM2
+// IC2->PA1 for GPS 1pps signal
+// IC1->PA0 for Reciprocal frequency counting mode (Interrupt)
+void FRQ_CUNTR::initialize_TIMz(void)
+{
+ // Initialize Timer2(32bit) for an internal(100MHz) up counter mode
+ RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
+ // count_up + div by 1
+ TIM2->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD));
+ // only counter overflow for interrupt
+ TIM2->CR1 |= (uint16_t)TIM_CR1_URS;
+ // Up counter uses from 0 to max(32bit)
+ TIM2->ARR = 0xffffffff;
+ TIM2->PSC = 0x0000; // 1/1
+ TIM2->CCER = 0; // Reset all
+ // input filter + input select
+ TIM2->CCMR1 &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S);
+ TIM2->CCMR1 |= TIM_CCMR1_CC1S_0;
+ TIM2->SMCR = 0; // Internal clock
+ TIM2->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter
+ // PA0 -> Input Capture pin as Timer2 IC1 for Reciprocal
+ GPIOA->AFR[0] &= 0xfffffff0;
+ GPIOA->AFR[0] |= GPIO_AF1_TIM2 << 0; // 0bit x 4
+ GPIOA->MODER &= ~(GPIO_MODER_MODER0); // AF
+ GPIOA->MODER |= GPIO_MODER_MODER0_1; // alternate function mode
+ GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR0); // PU
+ GPIOA->PUPDR |= GPIO_PUPDR_PUPDR0_0; // Pull-up mode
+ // Initialize Timer2 IC1
+ // input filter + input select
+ TIM2->CCMR1 &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S);
+ TIM2->CCMR1 |= (TIM_CCMR1_CC1S_0 + TIM_CCMR1_IC1F_1); // filter = fCLK/4
+ // positive edge
+ TIM2->CCER &= (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
+ TIM2->CCER |= (uint16_t)TIM_CCER_CC1E; // enable capture
+ // PA1 -> Input Capture pin as Timer2 IC2
+ GPIOA->AFR[0] &= 0xffffff0f;
+ GPIOA->AFR[0] |= GPIO_AF1_TIM2 << 4; // 1bit x 4
+ GPIOA->MODER &= ~(GPIO_MODER_MODER1); // AF
+ GPIOA->MODER |= GPIO_MODER_MODER1_1; // alternate function mode
+ GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR1); // PU
+ GPIOA->PUPDR |= GPIO_PUPDR_PUPDR1_0; // Pull-up mode
+ // Initialize Timer2 IC2
+ TIM2->CCER &= (uint16_t)~TIM_CCER_CC2E; // Disable the CC
+ TIM2->CCMR1 &= ~(TIM_CCMR1_IC2F | TIM_CCMR1_CC2S);
+ //TIM2->CCMR1 |= TIM_CCMR1_CC2S_0; // filter none
+ TIM2->CCMR1 |= (TIM_CCMR1_CC2S_0 + TIM_CCMR1_IC2F_1); // filter = fCLK/4
+ // positive edge
+ TIM2->CCER &= (uint16_t)~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
+ TIM2->CCER |= (uint16_t)TIM_CCER_CC2E; // enable capture
+ // Up counter based on gate time period
+ time_count_onepps = 0;
+ // Only for Debug purpose
+ // PA
+ PRINTF("\r\n// Timer2(32bit) for an internal up counter mode\r\n");
+ PRINTF("// Set GPIO for Timer2\r\n");
+ PRINTF("// PA0 -> Input Capture pin as Timer2 CH1/TI1\r\n");
+ PRINTF("// PA1 -> Input Capture pin as Timer2 CH2/TI2\r\n");
+ PRINTF("GPIOA->AFRL 0x%08x:0x%08x\r\n",&GPIOA->AFR[0], GPIOA->AFR[0]);
+ PRINTF("GPIOA->AFRH 0x%08x:0x%08x\r\n",&GPIOA->AFR[1], GPIOA->AFR[1]);
+ PRINTF("GPIOA->MODER 0x%08x:0x%08x\r\n",&GPIOA->MODER, GPIOA->MODER);
+ PRINTF("GPIOA->PUPDR 0x%08x:0x%08x\r\n",&GPIOA->PUPDR, GPIOA->PUPDR);
+ // TIM2
+ PRINTF("// PA0 -> Timer2 IC1\r\n");
+ PRINTF("// PA1 -> Timer2 IC2\r\n");
+ PRINTF("TIM2->CR1 0x%08x:0x%08x\r\n",&TIM2->CR1, TIM2->CR1);
+ PRINTF("TIM2->CR2 0x%08x:0x%08x\r\n",&TIM2->CR2, TIM2->CR2);
+ PRINTF("TIM2->ARR 0x%08x:0x%08x\r\n",&TIM2->ARR, TIM2->ARR);
+ PRINTF("TIM2->PSC 0x%08x:0x%08x\r\n",&TIM2->PSC, TIM2->PSC);
+ PRINTF("TIM2->CCMR1 0x%08x:0x%08x\r\n",&TIM2->CCMR1, TIM2->CCMR1);
+ PRINTF("TIM2->CCMR2 0x%08x:0x%08x\r\n",&TIM2->CCMR2, TIM2->CCMR2);
+ PRINTF("TIM2->CCER 0x%08x:0x%08x\r\n",&TIM2->CCER, TIM2->CCER);
+ PRINTF("TIM2->SMCR 0x%08x:0x%08x\r\n",&TIM2->SMCR, TIM2->SMCR);
+ // Interrupt Timer2 IC4(disable at this moment) & Overflow
+ timz_cnt_data = 0;
+ sw_ovrflw_timz = 0;
+ TIM2->SR = 0; // clear all IC/OC flag
+ TIM2->DIER = 0; // Disable all interrupt
+ TIM2->DIER = TIM_DIER_UIE; // set only overflow
+ NVIC_SetVector(TIM2_IRQn, (uint32_t)irq_ic_TIMz);
+ NVIC_ClearPendingIRQ(TIM2_IRQn);
+ NVIC_EnableIRQ(TIM2_IRQn);
+ PRINTF("TIM2->DIER 0x%08x:0x%08x\r\n\r\n",&TIM2->DIER, TIM2->DIER);
+}
+
+//------------------------------------------------------------------------------
+// Reciprocal measuremt
+//------------------------------------------------------------------------------
+void FRQ_CUNTR::start_action(void)
+{
+ __disable_irq();
+ TIM2->SR &= ~TIM_SR_CC1IF; // clear IC flag
+ TIM2->DIER |= TIM_DIER_CC1IE; // Enable IC1
+ __enable_irq();
+}
+
+//------------------------------------------------------------------------------
+// Frequency check for test & debug purpose
+//------------------------------------------------------------------------------
+// Read TIM1(+TIM3) Input frequency
+uint32_t FRQ_CUNTR::debug_read_input_frequency(double gatetime)
+{
+ TIM1->CR1 &= ~(uint16_t)TIM_CR1_CEN; // disable the TIM1 Counter
+ TIM3->CNT = 0;
+ TIM1->CNT = 0;
+ TIM1->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM1 Counter
+ wait(gatetime); // Gate time for count
+ TIM1->CR1 &= ~(uint16_t)TIM_CR1_CEN; // disable the TIM1 Counter
+ uint32_t freq = (TIM3->CNT << 16) + TIM1->CNT;
+ TIM1->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM1 Counter
+ PRINTF("Input freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq, gatetime);
+ return freq; // read counter
+}
+
+// Read TIM2 Clock frequency
+uint32_t FRQ_CUNTR::debug_read_base_clock_frequency(double gatetime)
+{
+ TIM2->CNT = 0;
+ wait(gatetime); // Gate time for count
+ uint32_t freq = TIM2->CNT; // read counter
+ PRINTF("Clock Counter=%10d, gate= %4.2f [Sec]\r\n", freq, gatetime);
+ return freq; // return counter data
+}
+
+// Dump all buffered data
+void FRQ_CUNTR::debug_printf_all_buffer(void)
+{
+ fdt_buffer.debug_print_all_buffer();
+}
+
+//------------------------------------------------------------------------------
+// Interrupt Handlers
+//------------------------------------------------------------------------------
+// GPS 1PPS signal interrupt (connected to TIM3 IC3, TIM1 IC2 and TIM2 IC2)
+// TIM3 IC3 Interrupt control
+void irq_ic_TIMxPy(void)
+{
+ // IC3 (GPS 1PPS)
+ if (TIM3->SR & TIM_SR_CC3IF){
+ TIM1->SR &= ~TIM_SR_CC2IF; // clear IC flag
+ TIM3->SR &= ~TIM_SR_CC3IF; // clear IC flag
+ TIM2->SR &= ~TIM_SR_CC2IF; // clear IC flag
+ timxpy_cnt_data = (TIM3->CCR3 << 16) + TIM1->CCR2; // 16+16 bit
+ timxpy_ready_flg = 1;
+ timz_cnt_data = TIM2->CCR2; // 32 bit
+ // data saves into the ring buffer / Unknown Freq.
+ fdt.freq_dt = timxpy_cnt_data;
+ fdt.f_sw_dt = sw_ovrflw_timxpy;
+ fdt.t_cnt = ++time_count;
+ fdt_buffer.ring_put_dt(fdt.f_1sec_dt);
+ // data saves into the ring buffer / F411 internal clock
+ onepps_dt.freq_dt = timz_cnt_data;
+ onepps_dt.f_sw_dt = sw_ovrflw_timz;
+ onepps_dt.t_cnt = ++time_count_onepps;
+ onepps_buf.ring_put_dt(onepps_dt.f_1sec_dt);
+ #if ACTIVE_LED_TIMX
+ irq_led1 = !irq_led1;
+ #endif // ACTIVE_LED
+ }
+ // TIM3 overflow
+ if (TIM3->SR & TIM_SR_UIF){
+ TIM3->SR &= ~TIM_SR_UIF;
+ ++sw_ovrflw_timxpy;
+ }
+}
+
+// Reciprocal data (TIM2 IC1)
+void irq_ic_TIMz(void)
+{
+ // IC1 (for reciprocal measurement)
+ if (TIM2->SR & TIM_SR_CC1IF){
+ TIM2->SR &= ~TIM_SR_CC1IF; // clear IC flag
+ uint32_t data = TIM2->CCR1;
+ if (recipro_step == 0){ // start measuring
+ recipro_start = data;
+ recipro_step = 1;
+ } else if (recipro_step == 1){ // stop
+ TIM2->DIER &= ~TIM_DIER_CC1IE; // disable IC4 interrupt
+ recipro_stop = data;
+ recipro_step = 2;
+ } else { // jsut in case
+ TIM2->DIER &= ~TIM_DIER_CC1IE; // disable IC4 interrupt
+ recipro_step = 0;
+ }
+ #if ACTIVE_LED_TIMZ
+ irq_led1 = !irq_led1;
+ #endif // ACTIVE_LED
+ }
+ // TIM2 overflow
+ if (TIM2->SR & TIM_SR_UIF){ // 32bit counter overflow
+ TIM2->SR &= ~TIM_SR_UIF;
+ ++sw_ovrflw_timz;
+ }
+}
+
+#endif // #if defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F446RE)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/fc_hw_f746.h Wed Nov 16 13:13:09 2016 +0000
@@ -0,0 +1,359 @@
+/*
+ * mbed Library / Frequency Counter using GPS 1PPS gate pulse
+ * Frequency Counter Hardware relataed program
+ * Only for ST DISCO-F746NG
+ *
+ * Re-started: October 5th, 2016 Change board -> DISCO-F746NG
+ * Re-started: October 17th, 2016 Separate common & HW related part
+ * Revised: November 13th, 2016
+ *
+ */
+
+#if defined(TARGET_STM32F746NG)
+
+// Following ring buffers are very big!! 4096 x 8(bytes) x 2(buff) = 64KB
+RingBuff<uint64_t> fdt_buffer; // RinBuffer for TIM8+4
+freq_one fdt; // frequency data in pack (interrupt)
+RingBuff<uint64_t> onepps_buf; // RinBuffer for TIM2
+freq_one onepps_dt; // frequency data in pack (interrupt)
+
+//------------------------------------------------------------------------------
+// Initialize TIM2 and TIM8+4
+//------------------------------------------------------------------------------
+// Initialize TIM8 & TIM4 as 32bit counter (TIM8(Low 16bit) + TIM4(High 16bit))
+// TIM8 clock input is unkown freq.(measuring freq.) and TIM4 is slave counter
+// 1PPS gate signal connected both TIM8 IC2, TIM4 IC3 (& TIM2 IC3)
+void FRQ_CUNTR::initialize_TIMxPy(void)
+{
+ // Timer8 input max freq.= 108MHz (@SystemCoreClock = 216MHz)
+ // PC6 -> Unkown frequency input pin as Timer8 CH1/TI1
+ RCC->AHB1ENR |= (RCC_AHB1ENR_GPIOCEN);
+ GPIOC->AFR[0] &= 0xf0ffffff;
+ GPIOC->AFR[0] |= GPIO_AF3_TIM8 << 24; // 6bit x 4
+ GPIOC->MODER &= ~(GPIO_MODER_MODER6); // AF
+ GPIOC->MODER |= GPIO_MODER_MODER6_1; // alternate function mode
+ GPIOC->PUPDR &= ~(GPIO_PUPDR_PUPDR6); // PU
+ GPIOC->PUPDR |= GPIO_PUPDR_PUPDR6_0; // Pull-up mode
+ // Initialize Timer8(16bit) for an external up counter mode
+ RCC->APB2ENR |= RCC_APB2ENR_TIM8EN;
+ // count_up + div by 1
+ TIM8->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD));
+ // update request only by overflow
+ TIM8->CR1 |= (uint16_t)TIM_CR1_URS;
+ TIM8->ARR = 0xffff; // Use 16bit full
+ TIM8->CCER = 0; // Reset all
+ // input filter + input select
+ TIM8->CCMR1 &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S);
+ TIM8->CCMR1 |= TIM_CCMR1_CC1S_0; // CC1 channel = TI1
+ // external mode 1
+ TIM8->SMCR &= ~(TIM_SMCR_ECE | TIM_SMCR_TS | TIM_SMCR_SMS);
+ // ECE must be ZERO!!!!
+ TIM8->SMCR |= ( TIM_TS_TI1FP1 | TIM_SLAVEMODE_EXTERNAL1);
+ TIM8->CR2 &= (uint16_t)~(TIM_CR2_TI1S | TIM_CR2_MMS);
+ TIM8->CR2 |= (uint16_t)TIM_CR2_MMS_1; // TRGO update
+ TIM8->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter
+ // PC7 -> Input Capture pin as Timer8 IC2
+ GPIOC->AFR[0] &= 0x0fffffff;
+ GPIOC->AFR[0] |= GPIO_AF3_TIM8 << 28; // 7bit x 4
+ GPIOC->MODER &= ~(GPIO_MODER_MODER7); // AF
+ GPIOC->MODER |= GPIO_MODER_MODER7_1; // alternate function mode
+ GPIOC->PUPDR &= ~(GPIO_PUPDR_PUPDR7); // PU
+ GPIOC->PUPDR |= GPIO_PUPDR_PUPDR7_0; // Pull-up mode
+ // Initialize Timer8 IC2
+ TIM8->CCER &= (uint16_t)~TIM_CCER_CC2E; // Disable the CC2
+ // input filter + input select
+ TIM8->CCMR1 &= ~(TIM_CCMR1_IC2F | TIM_CCMR1_CC2S);
+ TIM8->CCMR1 |= TIM_CCMR1_CC2S_0;
+ // positive edge
+ TIM8->CCER &= (uint16_t)~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
+ TIM8->CCER |= (uint16_t)TIM_CCER_CC2E; // enable capture
+ // Initialize Timer4(16bit) as slave counter of TIM8
+ // TIM8 overflow event -> ITR3 as Timer4 clock
+ RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
+ TIM4->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD));
+ // only counter overflow for interrupt
+ TIM4->CR1 |= (uint16_t)TIM_CR1_URS;
+ // Up counter uses from 0 to max(32bit)
+ TIM4->ARR = 0xffff; // Use 16bit full
+ TIM4->CCER = 0; // Reset all
+ // external mode 1
+ TIM4->SMCR &= ~(TIM_SMCR_ECE | TIM_SMCR_TS | TIM_SMCR_SMS);
+ TIM4->SMCR |= (TIM_TS_ITR3); // Set Internal Triger 3 (ITR3)
+ TIM4->SMCR |= (TIM_SLAVEMODE_EXTERNAL1); // ECE must be ZERO!!!!
+ TIM4->CR2 &= (uint16_t)~(TIM_CR2_TI1S | TIM_CR2_MMS);
+ TIM4->CR2 |= (uint16_t)TIM_CR2_MMS_1; // TRGO update
+ TIM4->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter
+ // PB8 -> Input Capture pin as Timer4 IC3
+ GPIOB->AFR[1] &= 0xfffffff0;
+ GPIOB->AFR[1] |= GPIO_AF2_TIM4 << 0; // (8-8)bit x 4
+ GPIOB->MODER &= ~(GPIO_MODER_MODER8); // AF
+ GPIOB->MODER |= GPIO_MODER_MODER8_1; // alternate function mode
+ GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPDR8); // PU
+ GPIOB->PUPDR |= GPIO_PUPDR_PUPDR8_0; // Pull-up mode
+ // Initialize Timer4 IC3
+ TIM4->CCER &= (uint16_t)~TIM_CCER_CC3E;
+ TIM4->CCMR2 &= ~(TIM_CCMR2_CC3S | TIM_CCMR2_IC3F);
+ TIM4->CCMR2 |= TIM_CCMR2_CC3S_0;
+ // positive edge
+ TIM4->CCER &= (uint16_t)~(TIM_CCER_CC3P | TIM_CCER_CC3NP);
+ TIM4->CCER |= (uint16_t)TIM_CCER_CC3E; // enable capture
+ // Up counter based on gate time period
+ time_count = 0;
+ // Only for Debug purpose
+ PRINTF("\r\n// Timer8(16bit high(max106MHz) clock)\r\n");
+ PRINTF("// and Timer4(16bit low clock) combined up counter\r\n");
+ PRINTF("// Set GPIO for Timer8&4\r\n");
+ // PB
+ PRINTF("// PB8 -> Input Capture pin as Timer4 CH3/TI3\r\n");
+ PRINTF("GPIOB->AFRL 0x%08x:0x%08x\r\n",&GPIOB->AFR[0], GPIOB->AFR[0]);
+ PRINTF("GPIOB->AFRH 0x%08x:0x%08x\r\n",&GPIOB->AFR[1], GPIOB->AFR[1]);
+ PRINTF("GPIOB->MODER 0x%08x:0x%08x\r\n",&GPIOB->MODER, GPIOB->MODER);
+ PRINTF("GPIOB->PUPDR 0x%08x:0x%08x\r\n",&GPIOB->PUPDR, GPIOB->PUPDR);
+ PRINTF("GPIOB->OTYPER 0x%08x:0x%08x\r\n",&GPIOB->OTYPER, GPIOB->OTYPER);
+ PRINTF("GPIOB->OSPEEDR 0x%08x:0x%08x\r\n",&GPIOB->OSPEEDR, GPIOB->OSPEEDR);
+ // PC
+ PRINTF("// PC6 -> unkown frequency input pin as Timer8 CH1/TI1\r\n");
+ PRINTF("// PC7 -> Input Capture pin as Timer8 CH2/TI2\r\n");
+ PRINTF("GPIOC->AFRL 0x%08x:0x%08x\r\n",&GPIOC->AFR[0], GPIOC->AFR[0]);
+ PRINTF("GPIOC->AFRH 0x%08x:0x%08x\r\n",&GPIOC->AFR[1], GPIOC->AFR[1]);
+ PRINTF("GPIOC->MODER 0x%08x:0x%08x\r\n",&GPIOC->MODER, GPIOC->MODER);
+ PRINTF("GPIOC->PUPDR 0x%08x:0x%08x\r\n",&GPIOC->PUPDR, GPIOC->PUPDR);
+ PRINTF("GPIOC->OTYPER 0x%08x:0x%08x\r\n",&GPIOC->OTYPER, GPIOC->OTYPER);
+ PRINTF("GPIOC->OSPEEDR 0x%08x:0x%08x\r\n",&GPIOC->OSPEEDR, GPIOC->OSPEEDR);
+ // TIM8
+ PRINTF("// PC6 -> Timer8(16bit) for an external up counter mode\r\n");
+ PRINTF("// PC7 -> Timer8 IC2\r\n");
+ PRINTF("TIM8->CR1 0x%08x:0x%08x\r\n",&TIM8->CR1, TIM8->CR1);
+ PRINTF("TIM8->CR2 0x%08x:0x%08x\r\n",&TIM8->CR2, TIM8->CR2);
+ PRINTF("TIM8->ARR 0x%08x:0x%08x\r\n",&TIM8->ARR, TIM8->ARR);
+ PRINTF("TIM8->PSC 0x%08x:0x%08x\r\n",&TIM8->PSC, TIM8->PSC);
+ PRINTF("TIM8->CCMR1 0x%08x:0x%08x\r\n",&TIM8->CCMR1, TIM8->CCMR1);
+ PRINTF("TIM8->CCMR2 0x%08x:0x%08x\r\n",&TIM8->CCMR2, TIM8->CCMR2);
+ PRINTF("TIM8->CCER 0x%08x:0x%08x\r\n",&TIM8->CCER, TIM8->CCER);
+ PRINTF("TIM8->SMCR 0x%08x:0x%08x\r\n",&TIM8->SMCR, TIM8->SMCR);
+ PRINTF("TIM8->DIER 0x%08x:0x%08x\r\n",&TIM8->DIER, TIM8->DIER);
+ // TIM4
+ PRINTF("// PB8 -> Timer4 IC3\r\n");
+ PRINTF("TIM4->CR1 0x%08x:0x%08x\r\n",&TIM4->CR1, TIM4->CR1);
+ PRINTF("TIM4->CR2 0x%08x:0x%08x\r\n",&TIM4->CR2, TIM4->CR2);
+ PRINTF("TIM4->ARR 0x%08x:0x%08x\r\n",&TIM4->ARR, TIM4->ARR);
+ PRINTF("TIM4->PSC 0x%08x:0x%08x\r\n",&TIM4->PSC, TIM4->PSC);
+ PRINTF("TIM4->CCMR1 0x%08x:0x%08x\r\n",&TIM4->CCMR1, TIM4->CCMR1);
+ PRINTF("TIM4->CCMR2 0x%08x:0x%08x\r\n",&TIM4->CCMR2, TIM4->CCMR2);
+ PRINTF("TIM4->CCER 0x%08x:0x%08x\r\n",&TIM4->CCER, TIM4->CCER);
+ PRINTF("TIM4->SMCR 0x%08x:0x%08x\r\n",&TIM4->SMCR, TIM4->SMCR);
+ // Interrupt Timer4 IC3 (NOT Timer8 IC2) & Overflow
+ timxpy_ready_flg = 0;
+ timxpy_cnt_data = 0;
+ sw_ovrflw_timxpy = 0;
+ TIM8->SR = 0; // clear all IC/OC flag
+ TIM4->SR = 0; // clear all IC/OC flag
+ TIM4->DIER = 0; // Reset all interrupt flag
+ TIM4->DIER = TIM_DIER_CC3IE + TIM_DIER_UIE;
+ NVIC_SetVector(TIM4_IRQn, (uint32_t)irq_ic_TIMxPy);
+ NVIC_ClearPendingIRQ(TIM4_IRQn);
+ NVIC_EnableIRQ(TIM4_IRQn);
+ PRINTF("TIM4->DIER 0x%08x:0x%08x\r\n\r\n",&TIM4->DIER, TIM4->DIER);
+ PRINTF("RCC->APB1ENR 0x%08x:0x%08x\r\n\r\n",&RCC->APB1ENR, RCC->APB1ENR);
+}
+
+// Initialize TIM2
+// IC3->PB10 for GPS 1pps signal
+// IC1->PA15 for Reciprocal frequency counting mode (Interrupt)
+void FRQ_CUNTR::initialize_TIMz(void)
+{
+ // Initialize Timer2(32bit) for an internal(108MHz) up counter mode
+ RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
+ // count_up + div by 1
+ TIM2->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD));
+ // only counter overflow for interrupt
+ TIM2->CR1 |= (uint16_t)TIM_CR1_URS;
+ // Up counter uses from 0 to max(32bit)
+ TIM2->ARR = 0xffffffff;
+ TIM2->PSC = 0x0000; // 1/1
+ TIM2->CCER = 0; // Reset all
+ // input filter + input select
+ TIM2->CCMR1 &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S);
+ TIM2->CCMR1 |= TIM_CCMR1_CC1S_0;
+ TIM2->SMCR = 0; // Internal clock
+ TIM2->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter
+ // PA15 -> Input Capture pin as Timer2 IC1
+ GPIOA->AFR[1] &= 0x0fffffff;
+ GPIOA->AFR[1] |= GPIO_AF1_TIM2 << 28; // 15-8 = 7bit x 4
+ GPIOA->MODER &= ~(GPIO_MODER_MODER15); // AF
+ GPIOA->MODER |= GPIO_MODER_MODER15_1; // alternate function mode
+ GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR15); // PU
+ GPIOA->PUPDR |= GPIO_PUPDR_PUPDR15_0; // Pull-up mode
+ // Initialize Timer2 IC1
+ // input filter + input select
+ TIM2->CCMR1 &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S);
+ TIM2->CCMR1 |= (TIM_CCMR1_CC1S_0 + TIM_CCMR1_IC1F_1); // filter = fCLK/4
+ // positive edge
+ TIM2->CCER &= (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
+ TIM2->CCER |= (uint16_t)TIM_CCER_CC1E; // enable capture
+ // PB10 -> Input Capture pin as Timer2 IC3 for Reciprocal
+ GPIOB->AFR[1] &= 0xfffff0ff;
+ GPIOB->AFR[1] |= GPIO_AF1_TIM2 << 8; // 10-8 = 2bit x 4
+ GPIOB->MODER &= ~(GPIO_MODER_MODER10); // AF
+ GPIOB->MODER |= GPIO_MODER_MODER10_1; // alternate function mode
+ GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPDR10); // PU
+ GPIOB->PUPDR |= GPIO_PUPDR_PUPDR10_0; // Pull-up mode
+ // Initialize Timer2 IC3
+ TIM2->CCER &= (uint16_t)~TIM_CCER_CC3E; // Disable the CC
+ TIM2->CCMR2 &= ~(TIM_CCMR2_IC3F | TIM_CCMR2_CC3S);
+ //TIM2->CCMR2 |= TIM_CCMR2_CC3S_0; // filter none
+ TIM2->CCMR2 |= (TIM_CCMR2_CC3S_0 + TIM_CCMR2_IC3F_1); // filter = fCLK/4
+ // positive edge
+ TIM2->CCER &= (uint16_t)~(TIM_CCER_CC3P | TIM_CCER_CC3NP);
+ TIM2->CCER |= (uint16_t)TIM_CCER_CC3E; // enable capture
+ // Up counter based on gate time period
+ time_count_onepps = 0;
+ // Only for Debug purpose
+ // PA
+ PRINTF("\r\n// Timer2(32bit) for an internal up counter mode\r\n");
+ PRINTF("// Set GPIO for Timer2\r\n");
+ PRINTF("// PA15 -> Input Capture pin as Timer2 CH1/TI1\r\n");
+ PRINTF("GPIOA->AFRL 0x%08x:0x%08x\r\n",&GPIOA->AFR[0], GPIOA->AFR[0]);
+ PRINTF("GPIOA->AFRH 0x%08x:0x%08x\r\n",&GPIOA->AFR[1], GPIOA->AFR[1]);
+ PRINTF("GPIOA->MODER 0x%08x:0x%08x\r\n",&GPIOA->MODER, GPIOA->MODER);
+ PRINTF("GPIOA->PUPDR 0x%08x:0x%08x\r\n",&GPIOA->PUPDR, GPIOA->PUPDR);
+ // PB
+ PRINTF("// PB10 -> Input Capture pin as Timer2 CH3/TI3\r\n");
+ PRINTF("GPIOB->AFRL 0x%08x:0x%08x\r\n",&GPIOB->AFR[0], GPIOB->AFR[0]);
+ PRINTF("GPIOB->AFRH 0x%08x:0x%08x\r\n",&GPIOB->AFR[1], GPIOB->AFR[1]);
+ PRINTF("GPIOB->MODER 0x%08x:0x%08x\r\n",&GPIOB->MODER, GPIOB->MODER);
+ PRINTF("GPIOB->PUPDR 0x%08x:0x%08x\r\n",&GPIOB->PUPDR, GPIOB->PUPDR);
+ // TIM2
+ PRINTF("// PA15 -> Timer2 IC1\r\n");
+ PRINTF("// PB10 -> Timer2 IC3\r\n");
+ PRINTF("TIM2->CR1 0x%08x:0x%08x\r\n",&TIM2->CR1, TIM2->CR1);
+ PRINTF("TIM2->CR2 0x%08x:0x%08x\r\n",&TIM2->CR2, TIM2->CR2);
+ PRINTF("TIM2->ARR 0x%08x:0x%08x\r\n",&TIM2->ARR, TIM2->ARR);
+ PRINTF("TIM2->PSC 0x%08x:0x%08x\r\n",&TIM2->PSC, TIM2->PSC);
+ PRINTF("TIM2->CCMR1 0x%08x:0x%08x\r\n",&TIM2->CCMR1, TIM2->CCMR1);
+ PRINTF("TIM2->CCMR2 0x%08x:0x%08x\r\n",&TIM2->CCMR2, TIM2->CCMR2);
+ PRINTF("TIM2->CCER 0x%08x:0x%08x\r\n",&TIM2->CCER, TIM2->CCER);
+ PRINTF("TIM2->SMCR 0x%08x:0x%08x\r\n",&TIM2->SMCR, TIM2->SMCR);
+ // Interrupt Timer2 IC4(disable at this moment) & Overflow
+ timz_cnt_data = 0;
+ sw_ovrflw_timz = 0;
+ TIM2->SR = 0; // clear all IC/OC flag
+ TIM2->DIER = 0; // Disable all interrupt
+ TIM2->DIER = TIM_DIER_UIE; // set only overflow
+ NVIC_SetVector(TIM2_IRQn, (uint32_t)irq_ic_TIMz);
+ NVIC_ClearPendingIRQ(TIM2_IRQn);
+ NVIC_EnableIRQ(TIM2_IRQn);
+ PRINTF("TIM2->DIER 0x%08x:0x%08x\r\n\r\n",&TIM2->DIER, TIM2->DIER);
+}
+
+//------------------------------------------------------------------------------
+// Reciprocal measuremt
+//------------------------------------------------------------------------------
+void FRQ_CUNTR::start_action(void)
+{
+ __disable_irq();
+ TIM2->SR &= ~TIM_SR_CC1IF; // clear IC flag
+ TIM2->DIER |= TIM_DIER_CC1IE; // Enable IC1
+ __enable_irq();
+}
+
+//------------------------------------------------------------------------------
+// Frequency check for test & debug purpose
+//------------------------------------------------------------------------------
+// Read TIM8(+TIM4) Input frequency
+uint32_t FRQ_CUNTR::debug_read_input_frequency(double gatetime)
+{
+ TIM8->CR1 &= ~(uint16_t)TIM_CR1_CEN; // disable the TIM8 Counter
+ TIM4->CNT = 0;
+ TIM8->CNT = 0;
+ TIM8->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM8 Counter
+ wait(gatetime); // Gate time for count
+ TIM8->CR1 &= ~(uint16_t)TIM_CR1_CEN; // disable the TIM8 Counter
+ uint32_t freq = (TIM4->CNT << 16) + TIM8->CNT;
+ TIM8->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM8 Counter
+ PRINTF("Input freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq, gatetime);
+ return freq; // read counter
+}
+
+// Read TIM2 Clock frequency
+uint32_t FRQ_CUNTR::debug_read_base_clock_frequency(double gatetime)
+{
+ TIM2->CNT = 0;
+ wait(gatetime); // Gate time for count
+ uint32_t freq = TIM2->CNT; // read counter
+ PRINTF("Clock Counter=%10d, gate= %4.2f [Sec]\r\n", freq, gatetime);
+ return freq; // return counter data
+}
+
+// Dump all buffered data
+void FRQ_CUNTR::debug_printf_all_buffer(void)
+{
+ fdt_buffer.debug_print_all_buffer();
+}
+
+//------------------------------------------------------------------------------
+// Interrupt Handlers
+//------------------------------------------------------------------------------
+// GPS 1PPS signal interrupt (connected to TIM4 IC3, TIM8 IC2 and TIM2 IC3)
+// TIM4 IC3 Interrupt control
+void irq_ic_TIMxPy(void)
+{
+ // IC3 (GPS 1PPS)
+ if (TIM4->SR & TIM_SR_CC3IF){
+ TIM8->SR &= ~TIM_SR_CC2IF; // clear IC flag
+ TIM4->SR &= ~TIM_SR_CC3IF; // clear IC flag
+ TIM2->SR &= ~TIM_SR_CC3IF; // clear IC flag
+ timxpy_cnt_data = (TIM4->CCR3 << 16) + TIM8->CCR2; // 16+16 bit
+ timxpy_ready_flg = 1;
+ timz_cnt_data = TIM2->CCR3; // 32 bit
+ // data saves into the ring buffer / Unknown Freq.
+ fdt.freq_dt = timxpy_cnt_data;
+ fdt.f_sw_dt = sw_ovrflw_timxpy;
+ fdt.t_cnt = ++time_count;
+ fdt_buffer.ring_put_dt(fdt.f_1sec_dt);
+ // data saves into the ring buffer / F746 internal clock
+ onepps_dt.freq_dt = timz_cnt_data;
+ onepps_dt.f_sw_dt = sw_ovrflw_timz;
+ onepps_dt.t_cnt = ++time_count_onepps;
+ onepps_buf.ring_put_dt(onepps_dt.f_1sec_dt);
+ #if ACTIVE_LED_TIMX
+ irq_led1 = !irq_led1;
+ #endif // ACTIVE_LED
+ }
+ // TIM4 overflow
+ if (TIM4->SR & TIM_SR_UIF){
+ TIM4->SR &= ~TIM_SR_UIF;
+ ++sw_ovrflw_timxpy;
+ }
+}
+
+// Reciprocal data (TIM2 IC1)
+void irq_ic_TIMz(void)
+{
+ // IC1 (for reciprocal measurement)
+ if (TIM2->SR & TIM_SR_CC1IF){
+ TIM2->SR &= ~TIM_SR_CC1IF; // clear IC flag
+ uint32_t data = TIM2->CCR1;
+ if (recipro_step == 0){ // start measuring
+ recipro_start = data;
+ recipro_step = 1;
+ } else if (recipro_step == 1){ // stop
+ TIM2->DIER &= ~TIM_DIER_CC1IE; // disable IC4 interrupt
+ recipro_stop = data;
+ recipro_step = 2;
+ } else { // jsut in case
+ TIM2->DIER &= ~TIM_DIER_CC1IE; // disable IC4 interrupt
+ recipro_step = 0;
+ }
+ #if ACTIVE_LED_TIMZ
+ irq_led1 = !irq_led1;
+ #endif // ACTIVE_LED
+ }
+ // TIM2 overflow
+ if (TIM2->SR & TIM_SR_UIF){ // 32bit counter overflow
+ TIM2->SR &= ~TIM_SR_UIF;
+ ++sw_ovrflw_timz;
+ }
+}
+
+#endif // defined(TARGET_STM32F746NG)
--- a/frq_cuntr_full.cpp Thu Jan 01 05:04:20 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,613 +0,0 @@
-/*
- * 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: January 1st, 2015
- *
- * 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.
- */
-
-#if defined(TARGET_NUCLEO_F411RE)
-
-#include "frq_cuntr_full.h"
-
-#ifdef DEBUG
-Serial pcm(USBTX, USBRX);
-DigitalOut debug_led(LED1);
-#endif
-
-#ifdef DEBUG
-#define BAUD(x) pcm.baud(x)
-#define PRINTF(...) pcm.printf(__VA_ARGS__)
-#else
-#define BAUD(x) {;}
-#define PRINTF(...) {;}
-#endif
-
-namespace Frequency_counter
-{
-// TIM2 OC
-static uint32_t oc_set_time0;
-static uint32_t oc_set_time1;
-static uint8_t new_gt_value;
-static uint32_t oc_hi_time;
-static uint32_t oc_lo_time;
-// TIM2 IC
-static uint8_t tim2_ready_flg;
-static uint32_t tim2_cnt_data;
-static uint32_t tim2_old_cnt_data;
-// TIM3+4 IC
-static uint8_t tim3p4_ready_flg;
-static uint32_t tim3p4_cnt_data;
-
-//-------------------------------------------------------------------------------------------------
-// Interrupt Handlers
-//-------------------------------------------------------------------------------------------------
-// TIM2 IC2 Interrupt control
-void irq_ic2_TIM2(void)
-{
- uint16_t reg;
- reg = TIM2->SR;
- if (reg & TIM_SR_CC2IF) {
- TIM2->SR &= ~TIM_SR_CC2IF; // clear IC flag
- tim2_old_cnt_data = tim2_cnt_data;
- tim2_cnt_data = TIM2->CCR2;
- tim2_ready_flg = 1;
-#if defined(DEBUG)
- debug_led = !debug_led;
-#endif // defined(DEBUG)
- } else if (reg & TIM_SR_CC3IF) { // Output Compare
- TIM2->SR &= ~TIM_SR_CC3IF; // clear IC flag
- if (GPIOB->IDR & 0x0400) { // Check PB10 status
- TIM2->CCR3 = TIM2->CCR3 + oc_hi_time;
- } else {
- TIM2->CCR3 = TIM2->CCR3 + oc_lo_time;
- if (new_gt_value) {
- new_gt_value = 0;
- oc_hi_time = oc_set_time0;
- oc_lo_time = oc_set_time1;
- }
- }
-#if defined(DEBUG)
- debug_led = !debug_led;
-#endif // defined(DEBUG)
- }
-}
-
-// TIM3 IC2 Interrupt control (same signal connected to TIM4 IC1)
-void irq_ic2_TIM3P4(void)
-{
- TIM3->SR &= ~TIM_SR_CC2IF; // clear IC flag
- TIM4->SR &= ~TIM_SR_CC1IF;
- tim3p4_cnt_data = (TIM4->CCR1 << 16) + TIM3->CCR2;
- tim3p4_ready_flg = 1;
-#if defined(DEBUG)
- debug_led = !debug_led;
-#endif // defined(DEBUG)
-}
-
-//---------------------------------------------------------------------------------------
-// Frequency Counter
-//---------------------------------------------------------------------------------------
-FRQ_CUNTR::FRQ_CUNTR(PinName f_in, double gt, double ex_clock): _pin(f_in)
-{
- // Don't change calling sequence!!
- set_external_clock(ex_clock); // 1st
- set_gate_time(gt); // 2nd
- initialize_Freq_counter(); // 3rd
-}
-
-// Set gate time
-double FRQ_CUNTR::set_gate_time(double gt)
-{
- if (gt < 0.05) {
- gate_time = 0.05;
- } else if (gt > 60.0) {
- gate_time = 60.0;
- } else {
- gate_time = gt;
- }
- oc_set_time0 = clk_hi_const;
- double gt_tmp0 = ex_clk_base * gate_time;
- uint32_t gt_tmp1 = (uint32_t)gt_tmp0;
- if ((gt_tmp0 - (double)gt_tmp1) >= 0.5) {
- ++gt_tmp1;
- }
- oc_set_time1 = gt_tmp1 - clk_hi_const;
- new_gt_value = 1;
- return gate_time;
-}
-
-// Read gate time
-double FRQ_CUNTR::read_gate_time(void)
-{
- return gate_time;
-}
-
-// Set External Clock Frequency
-void FRQ_CUNTR::set_external_clock(double ex_clock)
-{
-#if defined(BASE_EXTERNAL_CLOCK)
- ex_clock_freq = ex_clock;
- ex_clk_base = (uint32_t)(ex_clock_freq * 1000000); // MHz->Hz
- clk_hi_const = (uint32_t)(ex_clock_freq * 1000000 * 0.04); // 40mS
- uint32_t err = (uint32_t)(ex_clock_freq * 1000000 * 0.00001); // 10ppm error range
- clk_upper_limit = ex_clk_base + err;
- clk_lower_limit = ex_clk_base - err;
- PRINTF("EXTERNAL Clock mode\r\n");
-#else // defined(BASE_EXTERNAL_CLOCK)
- ex_clock_freq = 100; // Internal 100MHz
- ex_clk_base = 100000000; // MHz->Hz
- clk_hi_const = 4000000; // 40mS
- uint32_t err = 10000; // error range
- clk_upper_limit = ex_clk_base + err;
- clk_lower_limit = ex_clk_base - err;
- PRINTF("INTERNAL Clock mode\r\n");
-#endif // defined(BASE_EXTERNAL_CLOCK)
-}
-
-// Read new frequency data
-double FRQ_CUNTR::read_freq_data(void)
-{
- old_cntr_tim3p4 = counter_tim3p4;
- counter_tim3p4 = read_ic2_counter_TIM3P4();
- double freq0 = (double)(counter_tim3p4 - old_cntr_tim3p4);
- newest_frequency = freq0 / gate_time;
- return newest_frequency;
-}
-
-// Read status (new frequency data is available or not)
-uint32_t FRQ_CUNTR::status_freq_update(void)
-{
- return check_ic2_status_TIM3P4();
-}
-
-// Read status (new 1PPS data is available or not)
-uint32_t FRQ_CUNTR::status_1pps(void)
-{
- return check_ic2_status_TIM2();
-}
-
-// Read GPS 1PPS counter value
-uint32_t FRQ_CUNTR::set_1PPS_data(void)
-{
- uint32_t diff = tim2_cnt_data - tim2_old_cnt_data;
- if ((diff > clk_upper_limit) || (diff < clk_lower_limit)) {
- PRINTF("IC0 %d %d %d \r\n", diff, clk_upper_limit, clk_lower_limit);
- gps_ready = 0;
- return 0;
- } else {
- gps_ready = 1;
- onepps_cnt[onepps_num] = diff;
- if (++onepps_num >= CNT_BF_SIZE) {
- onepps_num = 0;
- onepps_buf_full = 1;
- }
- onepps_newest = diff;
- return diff;
- }
-}
-
-// Avarage measued data GPS 1PPS by 25MHz External Clock
-uint32_t FRQ_CUNTR::read_avarage_1pps(void)
-{
- uint64_t total = 0;
- if (onepps_buf_full == 1) {
- for (uint32_t i = 0; i < CNT_BF_SIZE; i++) {
- total += (uint64_t)onepps_cnt[i];
- }
- onepps_cnt_avarage = total / CNT_BF_SIZE;
- PRINTF("buf");
- } else {
- for (uint32_t i = 0; i < onepps_num; i++) {
- total += (uint64_t)onepps_cnt[i];
- }
- onepps_cnt_avarage = total / onepps_num;
- PRINTF("not");
- }
- PRINTF(" full, num= %3d , 1PPS/new= %9d\r\n", onepps_num, onepps_newest);
- return onepps_cnt_avarage;
-}
-
-// Newest measued data GPS 1PPS
-uint32_t FRQ_CUNTR::read_newest_1pps(void)
-{
- return onepps_newest;
-}
-
-// Check GPS condition
-uint8_t FRQ_CUNTR::status_gps(void)
-{
- return gps_ready;
-}
-
-//---------------------------------------------------------------------------------------
-// TIM2 (32bit Counter + IC + OC)
-//---------------------------------------------------------------------------------------
-// Read TIM2 captured counter value
-uint32_t FRQ_CUNTR::read_ic2_counter_TIM2(void)
-{
- return tim2_cnt_data; // return TIM2->CCR2;
-}
-
-// Check TIM2 IC2 status
-uint32_t FRQ_CUNTR::check_ic2_status_TIM2(void)
-{
- if (tim2_ready_flg == 0) {
- return 0;
- } else {
- tim2_ready_flg = 0;
- set_1PPS_data();
- return 1;
- }
-}
-
-// Check OC port status
-uint8_t FRQ_CUNTR::read_oc_port_status(void)
-{
- uint32_t p = GPIOB->IDR;
- if (p & 0x0400) { // Check PB10 status
- return 1;
- } else {
- return 0;
- }
-}
-
-//---------------------------------------------------------------------------------------
-// TIM3+TIM4 (32bit Counter + IC)
-//---------------------------------------------------------------------------------------
-// Read TIM3+4(as 32bit) captured counter value
-uint32_t FRQ_CUNTR::read_ic2_counter_TIM3P4(void)
-{
- return tim3p4_cnt_data;
-}
-
-// Check TIM3 IC2 & TIM4 IC1 status
-uint32_t FRQ_CUNTR::check_ic2_status_TIM3P4(void)
-{
- if (tim3p4_ready_flg == 0) {
- return 0;
- } else {
- tim3p4_ready_flg = 0;
- return 1;
- }
-}
-
-//---------------------------------------------------------------------------------------
-// Frequency check for test purpose
-//---------------------------------------------------------------------------------------
-// Read TIM2 Clock frequency
-uint32_t FRQ_CUNTR::read_frequency_TIM2(float gate_time)
-{
- uint32_t freq = 0;
- TIM2->CNT = 0;
- wait(gate_time); // Gate time for count
- freq = TIM2->CNT; // read counter
- PRINTF("Clock freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq, gate_time);
- return freq; // return counter data
-}
-
-// Read TIM3(+TIM4) Input frequency
-uint32_t FRQ_CUNTR::read_frequency_TIM3P4(float gate_time)
-{
- uint32_t freq0 = 0;
- uint32_t freq1 = 0;
- TIM3->CNT = 0;
- TIM4->CNT = 0;
- TIM3->CNT = 0;
- wait(gate_time); // Gate time for count
- freq0 = TIM3->CNT;
- freq1 = TIM4->CNT;
- freq0 = (freq1 << 16) + freq0;
- PRINTF("Input freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq0, gate_time);
- return freq0; // read counter
-}
-
-//---------------------------------------------------------------------------------------
-// Clock output for test purpose
-//---------------------------------------------------------------------------------------
-// Output internal clock
-void FRQ_CUNTR::port_mco1_mco2_set(uint8_t select)
-{
- // PA8 -> MCO_1
- GPIOA->AFR[1] &= 0xfffffff0;
- GPIOA->AFR[1] |= GPIO_AF0_MCO << 0;
- GPIOA->MODER &= ~(GPIO_MODER_MODER8); // AF
- GPIOA->MODER |= GPIO_MODER_MODER8_1;
- GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_8); // Output Push-Pull=0
- GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8;// Speed full=11
- GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR8); // Pull-up=01
- GPIOA->PUPDR |= GPIO_PUPDR_PUPDR8_0;
- // PC9 -> MCO_2
- GPIOC->AFR[1] &= 0xffffff0f;
- GPIOC->AFR[1] |= GPIO_AF0_MCO << 4;
- GPIOC->MODER &= ~(GPIO_MODER_MODER9); // AF
- GPIOC->MODER |= GPIO_MODER_MODER9_1;
- GPIOC->OTYPER &= ~(GPIO_OTYPER_OT_9); // Output Push-Pull=0
- GPIOC->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9;// Speed full=11
- GPIOC->PUPDR &= ~(GPIO_PUPDR_PUPDR9); // Pull-up=01
- GPIOC->PUPDR |= GPIO_PUPDR_PUPDR9_0;
- // Select output clock source
- RCC->CFGR &= 0x009fffff;
- if (select == 1) {
- // MC01 output HSE 1/1, MCO2 output SYSCLK 1/1
- // MCO2 MCO2PRE MCO1PRE MCO1
- RCC->CFGR |= (0x0 << 30) + (0x0 << 27) + (0x0 << 24) + (0x2 << 21);
- PRINTF("Set MCO1(PA8):HSE/1, MCO2(PC9):SYSCLK/1\r\n");
- } else if (select == 2) {
- // MC01 output HSE 1/2, MCO2 output SYSCLK 1/2
- // MCO2 MCO2PRE MCO1PRE MCO1
- RCC->CFGR |= (0x0 << 30) + (0x4 << 27) + (0x4 << 24) + (0x2 << 21);
- PRINTF("Set MCO1(PA8):HSE/2, MCO2(PC9):SYSCLK/2\r\n");
- } else { // select = 4 and other wrong order
- // MC01 output HSE 1/4, MCO2 output SYSCLK 1/4
- // MCO2 MCO2PRE MCO1PRE MCO1
- RCC->CFGR |= (0x0 << 30) + (0x6 << 27) + (0x6 << 24) + (0x2 << 21);
- PRINTF("Set MCO1(PA8):HSE/4, MCO2(PC9):SYSCLK/4\r\n");
- }
-}
-
-//---------------------------------------------------------------------------------------
-// Initialize TIM2 and TIM3+4
-//---------------------------------------------------------------------------------------
-void FRQ_CUNTR::initialize_Freq_counter(void)
-{
- initialize_TIM2();
- initialize_TIM3P4();
-}
-
-// Initialize TIM2
-// Internal clock (100MHz) or External clock(?MHz) and IC2 for GPS 1pps signal measurement
-void FRQ_CUNTR::initialize_TIM2(void)
-{
-#if defined(BASE_EXTERNAL_CLOCK)
- // PA0 -> Counter frequency input pin as Timer2 CH1/ETR
- RCC->AHB1ENR |= (RCC_AHB1ENR_GPIOAEN);
- GPIOA->AFR[0] &= 0xfffffff0;
- GPIOA->AFR[0] |= GPIO_AF1_TIM2;
- GPIOA->MODER &= ~(GPIO_MODER_MODER0); // AF
- GPIOA->MODER |= GPIO_MODER_MODER0_1;
- GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR0); // PU
- GPIOA->PUPDR |= GPIO_PUPDR_PUPDR0_0;
- // Initialize Timer2(32bit) for an external up counter mode
- RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
- TIM2->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD));// count_up + div by 1
- TIM2->CR1 |= TIM_CR1_URS;
- TIM2->ARR = 0xffffffff;
- TIM2->PSC = 0x0000;
- TIM2->CCER &= (uint16_t)~TIM_CCER_CC1E; // Disable the CC1
- TIM2->CCMR1 &= (uint16_t)~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S); // input filter + input select
- TIM2->CCMR1 |= (uint16_t)TIM_CCMR1_CC1S_0;
- TIM2->CCER &= (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NE | TIM_CCER_CC1NP); // positive edge
- TIM2->SMCR = (uint16_t)(TIM_SMCR_ECE| TIM_SMCR_ETPS_0 | TIM_SMCR_TS); // clock/2 !!
- TIM2->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter
-#else // defined(BASE_EXTERNAL_CLOCK)
- // Initialize Timer2(32bit) for an internal up counter mode
- RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
- TIM2->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD)); // count_up + div by 1
- TIM2->CR1 |= TIM_CR1_URS;
- TIM2->ARR = 0xffffffff;
- TIM2->PSC = 0x0000;
- TIM2->CCER &= (uint16_t)~TIM_CCER_CC1E; // Disable the CC1
- TIM2->SMCR &= (uint16_t)~(TIM_SMCR_ECE | TIM_SMCR_TS | TIM_SMCR_SMS);
- TIM2->SMCR |= (uint16_t)0; // Internal clock = 100MHz
- TIM2->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter
-#endif // defined(BASE_EXTERNAL_CLOCK)
- // PA1 -> Input Capture pin as Timer2 IC2
- GPIOA->AFR[0] &= 0xffffff0f;
- GPIOA->AFR[0] |= GPIO_AF1_TIM2 << 4;
- GPIOA->MODER &= ~(GPIO_MODER_MODER1); // AF
- GPIOA->MODER |= GPIO_MODER_MODER1_1;
- GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR1);
- GPIOA->PUPDR |= GPIO_PUPDR_PUPDR1_0; // PU
- // Initialize Timer2 I.C.2
- TIM2->CCER &= (uint16_t)~TIM_CCER_CC2E; // Disable the CC2
- TIM2->CCMR1 &= (uint16_t)~(TIM_CCMR1_IC2F | TIM_CCMR1_CC2S);// input filter + input select
- TIM2->CCMR1 |= (uint16_t)TIM_CCMR1_CC2S_0;
- TIM2->CCER &= (uint16_t)~(TIM_CCER_CC2P | TIM_CCER_CC2NP); // positive edge
- TIM2->CCER |= (uint16_t)TIM_CCER_CC2E; // enable capture
- // PB10 -> Output Compare pin as Timer2 CH3/OC3
- GPIOB->AFR[1] &= 0xfffff0ff;
- GPIOB->AFR[1] |= GPIO_AF1_TIM2 << 8;
- GPIOB->MODER &= ~(GPIO_MODER_MODER10); // AF
- GPIOB->MODER |= GPIO_MODER_MODER10_1;
- GPIOB->OTYPER &= ~(GPIO_OTYPER_OT_10);// Output Push-Pull=0
- GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR10;// Speed full=11
- GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPDR10); // Pull-up=01
- GPIOB->PUPDR |= GPIO_PUPDR_PUPDR10_0;
- // Initialize Timer2 O.C.3
- TIM2->CCER &= (uint16_t)~TIM_CCER_CC3E; // Reset the CC3E Bit
- TIM2->CCMR2 &= (uint16_t)~(TIM_CCMR2_OC3M | TIM_CCMR2_CC3S |
- TIM_CCMR2_OC3PE | TIM_CCMR2_OC3CE | TIM_CCMR2_OC3FE);
- TIM2->CCMR2 |= (TIM_CCMR2_OC3M_0 | TIM_CCMR2_OC3M_1);
- TIM2->CCER &= (uint16_t)~TIM_CCER_CC3P;// Reset the Output Polarity level
- TIM2->CCER |= (uint16_t)TIM_CCER_CC3E; // Set the CC3E Bit
- new_gt_value = 0;
- oc_hi_time = oc_set_time0;
- oc_lo_time = oc_set_time1;
- TIM2->CCR3 = TIM2->CNT + oc_hi_time;// Set the Capture Compare Register value
- // Only for Debug purpose
- BAUD(9600);
- // PA
- PRINTF("\r\n// Timer2(32bit) for an internal up counter mode\r\n");
- PRINTF("// PA1 -> Input Capture pin as Timer2 CH2/TI2\r\n");
- PRINTF("GPIOA->AFR[0]0x%08x:0x%08x\r\n",&GPIOA->AFR[0], GPIOA->AFR[0]);
- PRINTF("GPIOA->AFR[1]0x%08x:0x%08x\r\n",&GPIOA->AFR[1], GPIOA->AFR[1]);
- PRINTF("GPIOA->MODER 0x%08x:0x%08x\r\n",&GPIOA->MODER, GPIOA->MODER);
- PRINTF("GPIOA->PUPDR 0x%08x:0x%08x\r\n",&GPIOA->PUPDR, GPIOA->PUPDR);
- // PB
- PRINTF("// PB10 -> Output Compare pin as Timer2 CH3/TI3\r\n");
- PRINTF("GPIOB->AFR[0]0x%08x:0x%08x\r\n",&GPIOB->AFR[0], GPIOB->AFR[0]);
- PRINTF("GPIOB->AFR[1]0x%08x:0x%08x\r\n",&GPIOB->AFR[1], GPIOB->AFR[1]);
- PRINTF("GPIOB->MODER 0x%08x:0x%08x\r\n",&GPIOB->MODER, GPIOB->MODER);
- PRINTF("GPIOB->PUPDR 0x%08x:0x%08x\r\n",&GPIOB->PUPDR, GPIOB->PUPDR);
- // TIM2
- PRINTF("// PA1 -> Timer2 IC2\r\n");
- PRINTF("// PB10-> Timer2 OC3\r\n");
- PRINTF("TIM2->CR1 0x%08x:0x%08x\r\n",&TIM2->CR1, TIM2->CR1);
- PRINTF("TIM2->ARR 0x%08x:0x%08x\r\n",&TIM2->ARR, TIM2->ARR);
- PRINTF("TIM2->PSC 0x%08x:0x%08x\r\n",&TIM2->PSC, TIM2->PSC);
- PRINTF("TIM2->CCMR1 0x%08x:0x%08x\r\n",&TIM2->CCMR1, TIM2->CCMR1);
- PRINTF("TIM2->CCMR2 0x%08x:0x%08x\r\n",&TIM2->CCMR2, TIM2->CCMR2);
- PRINTF("TIM2->CCER 0x%08x:0x%08x\r\n",&TIM2->CCER, TIM2->CCER);
- PRINTF("TIM2->SMCR 0x%08x:0x%08x\r\n",&TIM2->SMCR, TIM2->SMCR);
- PRINTF("TIM2->CCR3 0x%08x:0x%08x\r\n\r\n",&TIM2->CCR3, TIM2->CCR3);
- // Interrupt Timer2 IC2
- for (uint32_t i = 0; i < CNT_BF_SIZE; i++) {
- onepps_cnt[i] = 0;
- }
- onepps_num = 0;
- onepps_ready_flg = 0;
- onepps_buf_full = 0;
- onepps_cnt_avarage = 0;
- tim2_ready_flg = 0;
- tim2_cnt_data = 0;
- tim2_old_cnt_data = 0;
- TIM2->SR &= ~(TIM_SR_CC2IF + TIM_SR_CC3IF); // clear IC flag
- TIM2->DIER |= TIM_DIER_CC2IE + TIM_DIER_CC3IE;
- NVIC_SetVector(TIM2_IRQn, (uint32_t)irq_ic2_TIM2);
- NVIC_ClearPendingIRQ(TIM2_IRQn);
- NVIC_EnableIRQ(TIM2_IRQn);
-}
-
-// Initialize TIM3 and TIM4 as 32bit counter (TIM3(16bit) + TIM4(16bit))
-// TIM3 clock input is unkown freq.(measuring freq.) and TIM4 is slave counter
-// 1sec gate signal connected both TIM3 IC2 and TIM4 IC1
-void FRQ_CUNTR::initialize_TIM3P4(void)
-{
- // PC6 -> Unkown frequency input pin as Timer3 CH1/TI1
- RCC->AHB1ENR |= (RCC_AHB1ENR_GPIOCEN);
- GPIOC->AFR[0] &= 0xf0ffffff;
- GPIOC->AFR[0] |= GPIO_AF2_TIM3 << 24;
- GPIOC->MODER &= ~(GPIO_MODER_MODER6); // AF
- GPIOC->MODER |= GPIO_MODER_MODER6_1;
- GPIOC->PUPDR &= ~(GPIO_PUPDR_PUPDR6);
- GPIOC->PUPDR |= GPIO_PUPDR_PUPDR6_0; // PU
- // Initialize Timer3(16bit) for an external up counter mode
- RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
- TIM3->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD));// count_up + div by 1
- TIM3->CR1 |= (uint16_t)TIM_CR1_URS;
- TIM3->ARR = 0xffff;
- TIM3->CCER &= (uint16_t)~TIM_CCER_CC1E; // Disable the CC1
- TIM3->CCMR1 &= (uint16_t)~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S); // input filter + input select
- TIM3->CCMR1 |= (uint16_t)TIM_CCMR1_CC1S_0;
- TIM3->CCER &= (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NE | TIM_CCER_CC1NP);// positive edge
- TIM3->SMCR &= (uint16_t)~(TIM_SMCR_ECE | TIM_SMCR_TS | TIM_SMCR_SMS);// external mode 1
- TIM3->SMCR |= (uint16_t)( TIM_TS_TI1FP1 | TIM_SLAVEMODE_EXTERNAL1); // ECE must be ZERO!!!!
- TIM3->CR2 &= (uint16_t)~(TIM_CR2_TI1S | TIM_CR2_MMS);
- TIM3->CR2 |= (uint16_t)TIM_CR2_MMS_1; // TRGO update
- TIM3->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter
- // Initialize Timer4(16bit) for an slave up counter of TIM3
- RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
- TIM4->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD));// count_up + div by 1
- TIM4->CR1 |= (uint16_t)TIM_CR1_URS;
- TIM4->ARR = 0xffff;
- TIM4->CCER &= (uint16_t)TIM_CCER_CC1E; // Capture enable
- TIM4->SMCR &= (uint16_t)~(TIM_SMCR_ECE | TIM_SMCR_TS | TIM_SMCR_SMS);// external mode 1
- TIM4->SMCR |= (uint16_t)( TIM_TS_ITR2 | TIM_SLAVEMODE_EXTERNAL1);// ECE must be ZERO!!!!
- TIM4->CR2 &= (uint16_t)~(TIM_CR2_TI1S | TIM_CR2_MMS);
- TIM4->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter
- // PC7 -> Input Capture pin as Timer3 IC2
- GPIOC->AFR[0] &= 0x0fffffff;
- GPIOC->AFR[0] |= GPIO_AF2_TIM3 << 28;
- GPIOC->MODER &= ~(GPIO_MODER_MODER7); // AF
- GPIOC->MODER |= GPIO_MODER_MODER7_1;
- GPIOC->PUPDR &= ~(GPIO_PUPDR_PUPDR7);
- GPIOC->PUPDR |= GPIO_PUPDR_PUPDR7_0; // PU
- // Initialize Timer3 IC2
- TIM3->CCER &= (uint16_t)~TIM_CCER_CC2E; // Disable the CC2
- TIM3->CCMR1 &= (uint16_t)~(TIM_CCMR1_IC2F | TIM_CCMR1_CC2S);// input filter + input select
- TIM3->CCMR1 |= (uint16_t)TIM_CCMR1_CC2S_0;
- TIM3->CCER &= (uint16_t)~(TIM_CCER_CC2P | TIM_CCER_CC2NP); // positive edge
- TIM3->CCER |= (uint16_t)TIM_CCER_CC2E; // enable capture
- // PB6 -> Input Capture pin as Timer4 IC1
- GPIOB->AFR[0] &= 0xf0ffffff;
- GPIOB->AFR[0] |= GPIO_AF2_TIM4 << 24;
- GPIOB->MODER &= ~(GPIO_MODER_MODER6); // AF
- GPIOB->MODER |= GPIO_MODER_MODER6_1;
- GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPDR6);
- GPIOB->PUPDR |= GPIO_PUPDR_PUPDR6_0; // Pull-up=01
- // Initialize Timer4 IC1
- TIM4->CCER &= (uint16_t)~TIM_CCER_CC1E;
- TIM4->CCMR1 &= ((uint16_t)~TIM_CCMR1_CC1S) & ((uint16_t)~TIM_CCMR1_IC1F);
- TIM4->CCMR1 |= (uint16_t)TIM_CCMR1_CC1S_0;
- TIM4->CCER &= (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP); // positive edge
- TIM4->CCER |= (uint16_t)TIM_CCER_CC1E; // enable capture
- // Only for Debug purpose
- // PB
- PRINTF("// PB6 -> Input Capture pin as Timer4 CH1/TI1\r\n");
- PRINTF("GPIOB->AFR[0]0x%08x:0x%08x\r\n",&GPIOB->AFR[0], GPIOB->AFR[0]);
- PRINTF("GPIOB->AFR[1]0x%08x:0x%08x\r\n",&GPIOB->AFR[1], GPIOB->AFR[1]);
- PRINTF("GPIOB->MODER 0x%08x:0x%08x\r\n",&GPIOB->MODER, GPIOB->MODER);
- PRINTF("GPIOB->PUPDR 0x%08x:0x%08x\r\n",&GPIOB->PUPDR, GPIOB->PUPDR);
- PRINTF("GPIOB->OTYPER 0x%08x:0x%08x\r\n",&GPIOB->OTYPER, GPIOB->OTYPER);
- PRINTF("GPIOB->OSPEEDR 0x%08x:0x%08x\r\n",&GPIOB->OSPEEDR, GPIOB->OSPEEDR);
- // PC
- PRINTF("// PC6 -> unkown frequency input pin as Timer3 CH1/TI1\r\n");
- PRINTF("// PC7 -> Input Capture pin as Timer3 CH2/TI2\r\n");
- PRINTF("GPIOC->AFR[0]0x%08x:0x%08x\r\n",&GPIOC->AFR[0], GPIOC->AFR[0]);
- PRINTF("GPIOC->AFR[1]0x%08x:0x%08x\r\n",&GPIOC->AFR[1], GPIOC->AFR[1]);
- PRINTF("GPIOC->MODER 0x%08x:0x%08x\r\n",&GPIOC->MODER, GPIOC->MODER);
- PRINTF("GPIOC->PUPDR 0x%08x:0x%08x\r\n",&GPIOC->PUPDR, GPIOC->PUPDR);
- PRINTF("GPIOC->OTYPER 0x%08x:0x%08x\r\n",&GPIOC->OTYPER, GPIOC->OTYPER);
- PRINTF("GPIOC->OSPEEDR 0x%08x:0x%08x\r\n",&GPIOC->OSPEEDR, GPIOC->OSPEEDR);
- // TIM3
- PRINTF("// PC6 -> Timer3(16bit) for an external up counter mode\r\n");
- PRINTF("// PC7 -> Timer3 IC2\r\n");
- PRINTF("TIM3->CR1 0x%08x:0x%08x\r\n",&TIM3->CR1, TIM3->CR1);
- PRINTF("TIM3->ARR 0x%08x:0x%08x\r\n",&TIM3->ARR, TIM3->ARR);
- PRINTF("TIM3->PSC 0x%08x:0x%08x\r\n",&TIM3->PSC, TIM3->PSC);
- PRINTF("TIM3->CCMR1 0x%08x:0x%08x\r\n",&TIM3->CCMR1, TIM3->CCMR1);
- PRINTF("TIM3->CCMR2 0x%08x:0x%08x\r\n",&TIM3->CCMR2, TIM3->CCMR2);
- PRINTF("TIM3->CCER 0x%08x:0x%08x\r\n",&TIM3->CCER, TIM3->CCER);
- PRINTF("TIM3->SMCR 0x%08x:0x%08x\r\n",&TIM3->SMCR, TIM3->SMCR);
- // TIM4
- PRINTF("// none-> Timer4(16bit) for an slave counter\r\n");
- PRINTF("// PB6 -> Timer4 IC1\r\n");
- PRINTF("TIM4->CR1 0x%08x:0x%08x\r\n",&TIM4->CR1, TIM4->CR1);
- PRINTF("TIM4->ARR 0x%08x:0x%08x\r\n",&TIM4->ARR, TIM4->ARR);
- PRINTF("TIM4->PSC 0x%08x:0x%08x\r\n",&TIM4->PSC, TIM4->PSC);
- PRINTF("TIM4->CCMR1 0x%08x:0x%08x\r\n",&TIM4->CCMR1, TIM4->CCMR1);
- PRINTF("TIM4->CCMR2 0x%08x:0x%08x\r\n",&TIM4->CCMR2, TIM4->CCMR2);
- PRINTF("TIM4->CCER 0x%08x:0x%08x\r\n",&TIM4->CCER, TIM4->CCER);
- PRINTF("TIM4->SMCR 0x%08x:0x%08x\r\n\r\n",&TIM4->SMCR, TIM4->SMCR);
- PRINTF("RCC->APB1ENR 0x%08x:0x%08x\r\n\r\n",&RCC->APB1ENR, RCC->APB1ENR);
- // Interrupt Timer3 IC2
- tim3p4_ready_flg = 0;
- tim3p4_cnt_data = 0;
- TIM3->SR &= ~TIM_SR_CC2IF; // clear IC flag
- TIM4->SR &= ~TIM_SR_CC1IF;
- TIM3->DIER |= TIM_DIER_CC2IE;
- NVIC_SetVector(TIM3_IRQn, (uint32_t)irq_ic2_TIM3P4);
- NVIC_ClearPendingIRQ(TIM3_IRQn);
- NVIC_EnableIRQ(TIM3_IRQn);
-}
-
-//---------------------------------------------------------------------------------------
-// Only for Debug purpose
-//---------------------------------------------------------------------------------------
-void FRQ_CUNTR::debug_printf_internal_data(void)
-{
- PRINTF("Debug information\r\n");
- PRINTF("gate_time %f\r\n", gate_time);
- PRINTF("ex_clock_freq %f\r\n", ex_clock_freq);
- PRINTF("ex_clk_base %9d\r\n", ex_clk_base);
- PRINTF("clk_hi_const %9d\r\n", clk_hi_const);
- PRINTF("clk_upper_limit %9d\r\n", clk_upper_limit);
- PRINTF("clk_lower_limit %9d\r\n", clk_lower_limit);
- PRINTF("\r\n");
-}
-
-} // Frequency_counter
-
-#endif // #if defined(TARGET_NUCLEO_F411RE)
--- a/frq_cuntr_full.h Thu Jan 01 05:04:20 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-/*
- * 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: January 1st, 2015
- *
- * 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"
-
-// please comment out when normal run mode
-//#define DEBUG // use Communication with PC(UART)
-
-/*
- CAUTION:
- If you select internal clock (100MHz), you need consider PLL clock behavior.
- PLL clock drifts over 70Hz (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.
- Comment out "BASE_EXTERNAL_CLOCK" is only for checking!!
- */
-#define BASE_EXTERNAL_CLOCK
-
-// use avaraged 1pps data
-#define ONEPPS_AVE
-
-namespace Frequency_counter
-{
-
-#define CNT_BF_SIZE 120 // 1PPS data save size
-
-/** Frequency Counter program
- * Only for ST Nucleo F411RE Board
- *
- * @code
- * #include "mbed.h"
- *
- * using namespace Frequency_counter;
- *
- * // PC_6,PC_7 & PB_6 use for Timer3 & 4(16+16bit)
- * // PA_0,PA_1 & PB_10 use for Timer2(32bit)
- * // PA_8 & PC_7 use for MCO (Test purpose)
- * FRQ_CUNTR fc(PC_6, 1.0, 24.999982f); //Input port, gate time[sec] & External clock freq.
- *
- * int main() {
- * uint32_t counter_1pps = 0;
- * double new_frequency = 0;
- * // This is for test purpose
- * fc.port_mco1_mco2_set(4); // Clk/4 ->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();
- * printf("1PPS/ave = %9d , FREQUENCY = %11.3f\r\n", counter_1pps, new_frequency);
- * }
- * }
- * @endcode
- */
-
-class FRQ_CUNTR
-{
-public:
-
- /** Configure data pin (Not changeable)
- * @param Freq. input pin + Gate time[sec] + External clock[MHz]
- */
- FRQ_CUNTR(PinName f_in, double gt, double ex_clock);
-
- /** Set gate time
- * @param gate time [sec]
- * @return gate time (range 50mS to 1 minute)
- */
- double set_gate_time(double gt);
-
- /** Set external clock frequency
- * @param frequency e.g. 25.000000 [MHz]
- * @return none
- */
- void set_external_clock(double ex_clock);
-
- /** Read gate time
- * @param none
- * @return gate time (range 50mS to 1 minute)
- */
- double read_gate_time(void);
-
- /** 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
- */
- double read_freq_data(void);
-
- /** Read avarage measued data GPS 1PPS
- * @param none
- * @return Frequency
- */
- uint32_t read_avarage_1pps(void);
-
- /** Read newest measued data GPS 1PPS
- * @param none
- * @return Frequency
- */
- uint32_t read_newest_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);
-
- /** Read GPS status
- * @param none
- * @return 1: GPS is ready
- */
- uint8_t status_gps(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);
-
- /** This is a "DEBUG PURPOSE" function
- * print internal data (need to define "DEBUG"
- * @param none
- * @return none
- */
- void debug_printf_internal_data(void);
-
-protected:
- DigitalIn _pin;
-
- void initialize_Freq_counter(void); // Initialize timers
- // Internal clock (100MHz) or External clock(?MHz) 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:
- double newest_frequency;
- double gate_time;
- double ex_clock_freq;
- uint32_t ex_clk_base;
- uint32_t clk_hi_const;
- uint32_t clk_upper_limit;
- uint32_t clk_lower_limit;
- uint8_t gps_ready;
- // TIM2
- 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
