Frequency counter library only for NucleoF411RE

Dependents:   Frequency_Counter_w_GPS_1PPS

Committer:
kenjiArai
Date:
Sun Dec 21 12:14:46 2014 +0000
Revision:
2:194f82ad3041
Parent:
1:102230f2879d
Child:
3:339307e1dc0d
added new function and fixed bugs

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:bfdc6ed58a06 1 /*
kenjiArai 1:102230f2879d 2 * mbed Library / Frequency Counter with GPS 1PPS Compensation
kenjiArai 0:bfdc6ed58a06 3 * Frequency Counter Hardware relataed program
kenjiArai 1:102230f2879d 4 * Only for ST Nucleo F411RE
kenjiArai 0:bfdc6ed58a06 5 *
kenjiArai 0:bfdc6ed58a06 6 * Copyright (c) 2014 Kenji Arai / JH1PJL
kenjiArai 0:bfdc6ed58a06 7 * http://www.page.sannet.ne.jp/kenjia/index.html
kenjiArai 0:bfdc6ed58a06 8 * http://mbed.org/users/kenjiArai/
kenjiArai 0:bfdc6ed58a06 9 * Additional functions and modification
kenjiArai 0:bfdc6ed58a06 10 * started: October 18th, 2014
kenjiArai 2:194f82ad3041 11 * Revised: December 21st, 2014
kenjiArai 0:bfdc6ed58a06 12 *
kenjiArai 0:bfdc6ed58a06 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
kenjiArai 0:bfdc6ed58a06 14 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
kenjiArai 0:bfdc6ed58a06 15 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
kenjiArai 0:bfdc6ed58a06 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
kenjiArai 0:bfdc6ed58a06 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
kenjiArai 0:bfdc6ed58a06 18 */
kenjiArai 0:bfdc6ed58a06 19
kenjiArai 0:bfdc6ed58a06 20 #ifndef MBED_FRQ_CUNTR
kenjiArai 0:bfdc6ed58a06 21 #define MBED_FRQ_CUNTR
kenjiArai 0:bfdc6ed58a06 22
kenjiArai 0:bfdc6ed58a06 23 #include "mbed.h"
kenjiArai 0:bfdc6ed58a06 24
kenjiArai 2:194f82ad3041 25 //#define DEBUG // use Communication with PC(UART)
kenjiArai 2:194f82ad3041 26
kenjiArai 1:102230f2879d 27 /*
kenjiArai 1:102230f2879d 28 CAUTION:
kenjiArai 1:102230f2879d 29 If you select internal clock (100MHz), you need consider PLL clock behavior.
kenjiArai 2:194f82ad3041 30 PLL clock drifts over 70Hz (increase frequency) within 30 to 40 second
kenjiArai 1:102230f2879d 31 then suddenly back to low frequency and increase again.
kenjiArai 1:102230f2879d 32 Even you prepare precision external clock, this frequency drift cannot avoid.
kenjiArai 2:194f82ad3041 33 Comment out "BASE_EXTERNAL_CLOCK" is only for checking!!
kenjiArai 1:102230f2879d 34 */
kenjiArai 1:102230f2879d 35 #define BASE_EXTERNAL_CLOCK
kenjiArai 1:102230f2879d 36
kenjiArai 0:bfdc6ed58a06 37 namespace Frequency_counter
kenjiArai 0:bfdc6ed58a06 38 {
kenjiArai 1:102230f2879d 39
kenjiArai 1:102230f2879d 40 #define CNT_BF_SIZE 120 // 1PPS data save size
kenjiArai 1:102230f2879d 41
kenjiArai 1:102230f2879d 42 /** Frequency Counter program
kenjiArai 1:102230f2879d 43 * Only for ST Nucleo F411RE Board
kenjiArai 1:102230f2879d 44 *
kenjiArai 1:102230f2879d 45 * @code
kenjiArai 1:102230f2879d 46 * #include "mbed.h"
kenjiArai 1:102230f2879d 47 *
kenjiArai 2:194f82ad3041 48 * using namespace Frequency_counter;
kenjiArai 2:194f82ad3041 49 *
kenjiArai 2:194f82ad3041 50 * // PC_6,PC_7 & PB_6 use for Timer3 & 4(16+16bit)
kenjiArai 2:194f82ad3041 51 * // PA_0,PA_1 & PB_10 use for Timer2(32bit)
kenjiArai 2:194f82ad3041 52 * // PA_8 & PC_7 use for MCO (Test purpose)
kenjiArai 2:194f82ad3041 53 * FRQ_CUNTR fc(PC_6, 1.0, 50.000000);// Input port, gate time[sec] and External clock freq.
kenjiArai 1:102230f2879d 54 *
kenjiArai 1:102230f2879d 55 * int main() {
kenjiArai 2:194f82ad3041 56 * uint32_t counter_1pps = 0;
kenjiArai 2:194f82ad3041 57 * double new_frequency = 0;
kenjiArai 1:102230f2879d 58 * // This is for test purpose
kenjiArai 1:102230f2879d 59 * fc.port_mco1_mco2_set(2); // Clk/2 ->1/1(100MHz) cannot measure!!
kenjiArai 1:102230f2879d 60 * fc.read_frequency_TIM2(1.0); // read TIM2 source frequency (test)
kenjiArai 1:102230f2879d 61 * fc.read_frequency_TIM3P4(1.0); // read TIM3 source frequency (test)
kenjiArai 1:102230f2879d 62 * while(true) {
kenjiArai 1:102230f2879d 63 * while (fc.status_1pps() == 0) {;}
kenjiArai 1:102230f2879d 64 * counter_1pps = fc.read_avarage_1pps();
kenjiArai 1:102230f2879d 65 * while (fc.status_freq_update() == 0) {;}
kenjiArai 1:102230f2879d 66 * new_frequency = fc.read_freq_data();
kenjiArai 2:194f82ad3041 67 * PRINTF("1PPS/ave = %9d , FREQUENCY = %11.3f\r\n", counter_1pps, new_frequency);
kenjiArai 1:102230f2879d 68 * }
kenjiArai 1:102230f2879d 69 * }
kenjiArai 1:102230f2879d 70 * @endcode
kenjiArai 1:102230f2879d 71 */
kenjiArai 1:102230f2879d 72
kenjiArai 1:102230f2879d 73 class FRQ_CUNTR
kenjiArai 1:102230f2879d 74 {
kenjiArai 1:102230f2879d 75 public:
kenjiArai 2:194f82ad3041 76
kenjiArai 1:102230f2879d 77 /** Configure data pin (Not changeable)
kenjiArai 2:194f82ad3041 78 * @param Freq. input pin + Gate time[sec] + External clock[MHz]
kenjiArai 1:102230f2879d 79 */
kenjiArai 2:194f82ad3041 80 FRQ_CUNTR(PinName f_in, double gt, double ex_clock);
kenjiArai 1:102230f2879d 81
kenjiArai 1:102230f2879d 82 /** Set gate time
kenjiArai 1:102230f2879d 83 * @param gate time [sec]
kenjiArai 2:194f82ad3041 84 * @return gate time (range 50mS to 1 minute)
kenjiArai 1:102230f2879d 85 */
kenjiArai 1:102230f2879d 86 double set_gate_time(double gt);
kenjiArai 1:102230f2879d 87
kenjiArai 2:194f82ad3041 88 /** Read gate time
kenjiArai 2:194f82ad3041 89 * @param none
kenjiArai 2:194f82ad3041 90 * @return gate time (range 50mS to 1 minute)
kenjiArai 2:194f82ad3041 91 */
kenjiArai 2:194f82ad3041 92 double read_gate_time(void);
kenjiArai 2:194f82ad3041 93
kenjiArai 1:102230f2879d 94 /** Read status (new frequency data is available or not)
kenjiArai 1:102230f2879d 95 * @param none
kenjiArai 1:102230f2879d 96 * @return !=0: new data is avairable, 0: not yet
kenjiArai 1:102230f2879d 97 */
kenjiArai 1:102230f2879d 98 uint32_t status_freq_update(void);
kenjiArai 1:102230f2879d 99
kenjiArai 1:102230f2879d 100 /** Read new frequency data
kenjiArai 1:102230f2879d 101 * @param none
kenjiArai 1:102230f2879d 102 * @return frequency data
kenjiArai 1:102230f2879d 103 */
kenjiArai 2:194f82ad3041 104 double read_freq_data(void);
kenjiArai 0:bfdc6ed58a06 105
kenjiArai 1:102230f2879d 106 /** Read avarage measued data GPS 1PPS
kenjiArai 1:102230f2879d 107 * @param none
kenjiArai 1:102230f2879d 108 * @return Frequency
kenjiArai 1:102230f2879d 109 */
kenjiArai 1:102230f2879d 110 uint32_t read_avarage_1pps(void);
kenjiArai 1:102230f2879d 111
kenjiArai 1:102230f2879d 112 /** Read status (new 1PPS data is available or not)
kenjiArai 1:102230f2879d 113 * @param none
kenjiArai 1:102230f2879d 114 * @return !=0: new data is avairable, 0: not yet
kenjiArai 1:102230f2879d 115 */
kenjiArai 1:102230f2879d 116 uint32_t status_1pps(void);
kenjiArai 1:102230f2879d 117
kenjiArai 2:194f82ad3041 118 /** Read GPS status
kenjiArai 2:194f82ad3041 119 * @param none
kenjiArai 2:194f82ad3041 120 * @return 1: GPS is ready
kenjiArai 2:194f82ad3041 121 */
kenjiArai 2:194f82ad3041 122 uint8_t gps_status(void);
kenjiArai 2:194f82ad3041 123
kenjiArai 2:194f82ad3041 124 /** This is a "TEST PURPOSE" function
kenjiArai 1:102230f2879d 125 * Check PA0 pin input or internal clock frequency
kenjiArai 1:102230f2879d 126 * @param none
kenjiArai 1:102230f2879d 127 * @return Frequency
kenjiArai 1:102230f2879d 128 */
kenjiArai 1:102230f2879d 129 uint32_t read_frequency_TIM2(float gate_time);
kenjiArai 1:102230f2879d 130
kenjiArai 2:194f82ad3041 131 /** This is a "TEST PURPOSE" function
kenjiArai 1:102230f2879d 132 * Check PC6 pin input frequency
kenjiArai 1:102230f2879d 133 * @param none
kenjiArai 1:102230f2879d 134 * @return Frequency
kenjiArai 1:102230f2879d 135 */
kenjiArai 1:102230f2879d 136 uint32_t read_frequency_TIM3P4(float gate_time);
kenjiArai 1:102230f2879d 137
kenjiArai 2:194f82ad3041 138 /** This is a "TEST PURPOSE" function
kenjiArai 1:102230f2879d 139 * Output clock from pin PA8 & PC9 uses for MCO_1 & MCO_2
kenjiArai 1:102230f2879d 140 * @param none
kenjiArai 1:102230f2879d 141 * @return none
kenjiArai 1:102230f2879d 142 */
kenjiArai 1:102230f2879d 143 void port_mco1_mco2_set(uint8_t select);
kenjiArai 1:102230f2879d 144
kenjiArai 2:194f82ad3041 145 /** This is a "DEBUG PURPOSE" function
kenjiArai 2:194f82ad3041 146 * print internal data (need to define "DEBUG"
kenjiArai 2:194f82ad3041 147 * @param none
kenjiArai 2:194f82ad3041 148 * @return none
kenjiArai 2:194f82ad3041 149 */
kenjiArai 2:194f82ad3041 150 void debug_printf_internal_data(void);
kenjiArai 2:194f82ad3041 151
kenjiArai 1:102230f2879d 152 protected:
kenjiArai 1:102230f2879d 153 DigitalIn _pin;
kenjiArai 1:102230f2879d 154
kenjiArai 1:102230f2879d 155 void initialize_Freq_counter(void); // Initialize timers
kenjiArai 2:194f82ad3041 156 // Internal clock (100MHz) or External clock(?MHz) and IC2 for GPS 1pps signal measurement
kenjiArai 1:102230f2879d 157 void initialize_TIM2(void);
kenjiArai 1:102230f2879d 158 // Initialize TIM3 and TIM4 as 32bit counter (TIM3(16bit) + TIM4(16bit))
kenjiArai 1:102230f2879d 159 void initialize_TIM3P4(void);
kenjiArai 2:194f82ad3041 160 void set_external_clock(double ex_clock); // Set external clock data
kenjiArai 1:102230f2879d 161 uint32_t set_1PPS_data(void); // Set GPS 1PPS counter value
kenjiArai 1:102230f2879d 162 uint32_t read_ic2_counter_TIM2(void); // Read TIM2 captured counter value
kenjiArai 1:102230f2879d 163 uint32_t check_ic2_status_TIM2(void); // Check TIM2 IC2 status
kenjiArai 1:102230f2879d 164 uint32_t read_ic2_counter_TIM3P4(void); // Read TIM3+4(as 32bit) captured counter value
kenjiArai 1:102230f2879d 165 uint32_t check_ic2_status_TIM3P4(void); // Check TIM3 IC2 & TIM4 IC1 status
kenjiArai 1:102230f2879d 166 uint8_t read_oc_port_status(void); // Check TIM2 OC port
kenjiArai 1:102230f2879d 167
kenjiArai 1:102230f2879d 168 private:
kenjiArai 2:194f82ad3041 169 double newest_frequency;
kenjiArai 2:194f82ad3041 170 double gate_time;
kenjiArai 2:194f82ad3041 171 double ex_clock_freq;
kenjiArai 2:194f82ad3041 172 uint32_t ex_clk_base;
kenjiArai 2:194f82ad3041 173 uint32_t clk_hi_const;
kenjiArai 2:194f82ad3041 174 uint32_t clk_upper_limit;
kenjiArai 2:194f82ad3041 175 uint32_t clk_lower_limit;
kenjiArai 2:194f82ad3041 176 uint8_t gps_ready;
kenjiArai 1:102230f2879d 177 // TIM2
kenjiArai 1:102230f2879d 178 uint32_t counter_tim2;
kenjiArai 1:102230f2879d 179 uint32_t old_cntr_tim2;
kenjiArai 1:102230f2879d 180 // TIM3+4
kenjiArai 1:102230f2879d 181 uint32_t counter_tim3p4;
kenjiArai 1:102230f2879d 182 uint32_t old_cntr_tim3p4;
kenjiArai 1:102230f2879d 183 // 1PPS data
kenjiArai 1:102230f2879d 184 uint32_t onepps_newest;
kenjiArai 1:102230f2879d 185 uint32_t onepps_cnt[CNT_BF_SIZE];
kenjiArai 1:102230f2879d 186 uint32_t onepps_num;
kenjiArai 1:102230f2879d 187 uint64_t onepps_cnt_avarage;
kenjiArai 1:102230f2879d 188 uint8_t onepps_buf_full;
kenjiArai 1:102230f2879d 189 uint8_t onepps_ready_flg;
kenjiArai 2:194f82ad3041 190
kenjiArai 1:102230f2879d 191 };
kenjiArai 1:102230f2879d 192
kenjiArai 1:102230f2879d 193 /*
kenjiArai 1:102230f2879d 194 Interrupt handler does NOT work following code
kenjiArai 1:102230f2879d 195 NVIC_SetVector(TIM2_IRQn, (uint32_t)FRQ_CUNTR::irq_ic2_TIM2);
kenjiArai 1:102230f2879d 196 From this reason, I wrote below code and set interrupt handler out side "FRQ_CUNTR" class
kenjiArai 1:102230f2879d 197 NVIC_SetVector(TIM2_IRQn, (uint32_t)irq_ic2_TIM2);
kenjiArai 1:102230f2879d 198 */
kenjiArai 1:102230f2879d 199 void irq_ic2_TIM2(void); // TIM2 IC2 Interrupt control
kenjiArai 1:102230f2879d 200 void irq_ic2_TIM3P4(void); // TIM3 IC2 Interrupt control (same signal connected to TIM4 IC1)
kenjiArai 1:102230f2879d 201
kenjiArai 0:bfdc6ed58a06 202 } // Frequency_counter
kenjiArai 0:bfdc6ed58a06 203
kenjiArai 1:102230f2879d 204 #endif // MBED_FRQ_CUNTR