Frequency counter library using GPS 1PPS signal and temperature controlled 50MHz Base clock. Ported from F411 Frequency Counter.
Dependents: Frequency_Cntr_1PPS_F746ZG
Fork of Frq_cuntr_full by
Please refer following.
/users/kenjiArai/notebook/frequency-counters/
frq_cuntr_full.h@4:9d3b3f0a3882, 2015-01-01 (annotated)
- Committer:
- kenjiArai
- Date:
- Thu Jan 01 05:04:20 2015 +0000
- Revision:
- 4:9d3b3f0a3882
- Parent:
- 3:339307e1dc0d
Modified comments
Who changed what in which revision?
User | Revision | Line number | New 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 | 4:9d3b3f0a3882 | 11 | * Revised: January 1st, 2015 |
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 | 3:339307e1dc0d | 25 | // please comment out when normal run mode |
kenjiArai | 2:194f82ad3041 | 26 | //#define DEBUG // use Communication with PC(UART) |
kenjiArai | 2:194f82ad3041 | 27 | |
kenjiArai | 1:102230f2879d | 28 | /* |
kenjiArai | 1:102230f2879d | 29 | CAUTION: |
kenjiArai | 1:102230f2879d | 30 | If you select internal clock (100MHz), you need consider PLL clock behavior. |
kenjiArai | 2:194f82ad3041 | 31 | PLL clock drifts over 70Hz (increase frequency) within 30 to 40 second |
kenjiArai | 1:102230f2879d | 32 | then suddenly back to low frequency and increase again. |
kenjiArai | 1:102230f2879d | 33 | Even you prepare precision external clock, this frequency drift cannot avoid. |
kenjiArai | 2:194f82ad3041 | 34 | Comment out "BASE_EXTERNAL_CLOCK" is only for checking!! |
kenjiArai | 1:102230f2879d | 35 | */ |
kenjiArai | 1:102230f2879d | 36 | #define BASE_EXTERNAL_CLOCK |
kenjiArai | 1:102230f2879d | 37 | |
kenjiArai | 3:339307e1dc0d | 38 | // use avaraged 1pps data |
kenjiArai | 3:339307e1dc0d | 39 | #define ONEPPS_AVE |
kenjiArai | 3:339307e1dc0d | 40 | |
kenjiArai | 0:bfdc6ed58a06 | 41 | namespace Frequency_counter |
kenjiArai | 0:bfdc6ed58a06 | 42 | { |
kenjiArai | 1:102230f2879d | 43 | |
kenjiArai | 1:102230f2879d | 44 | #define CNT_BF_SIZE 120 // 1PPS data save size |
kenjiArai | 1:102230f2879d | 45 | |
kenjiArai | 1:102230f2879d | 46 | /** Frequency Counter program |
kenjiArai | 1:102230f2879d | 47 | * Only for ST Nucleo F411RE Board |
kenjiArai | 1:102230f2879d | 48 | * |
kenjiArai | 1:102230f2879d | 49 | * @code |
kenjiArai | 1:102230f2879d | 50 | * #include "mbed.h" |
kenjiArai | 1:102230f2879d | 51 | * |
kenjiArai | 2:194f82ad3041 | 52 | * using namespace Frequency_counter; |
kenjiArai | 2:194f82ad3041 | 53 | * |
kenjiArai | 2:194f82ad3041 | 54 | * // PC_6,PC_7 & PB_6 use for Timer3 & 4(16+16bit) |
kenjiArai | 2:194f82ad3041 | 55 | * // PA_0,PA_1 & PB_10 use for Timer2(32bit) |
kenjiArai | 2:194f82ad3041 | 56 | * // PA_8 & PC_7 use for MCO (Test purpose) |
kenjiArai | 4:9d3b3f0a3882 | 57 | * FRQ_CUNTR fc(PC_6, 1.0, 24.999982f); //Input port, gate time[sec] & External clock freq. |
kenjiArai | 1:102230f2879d | 58 | * |
kenjiArai | 1:102230f2879d | 59 | * int main() { |
kenjiArai | 2:194f82ad3041 | 60 | * uint32_t counter_1pps = 0; |
kenjiArai | 2:194f82ad3041 | 61 | * double new_frequency = 0; |
kenjiArai | 1:102230f2879d | 62 | * // This is for test purpose |
kenjiArai | 4:9d3b3f0a3882 | 63 | * fc.port_mco1_mco2_set(4); // Clk/4 ->1/1(100MHz) cannot measure!! |
kenjiArai | 1:102230f2879d | 64 | * fc.read_frequency_TIM2(1.0); // read TIM2 source frequency (test) |
kenjiArai | 1:102230f2879d | 65 | * fc.read_frequency_TIM3P4(1.0); // read TIM3 source frequency (test) |
kenjiArai | 1:102230f2879d | 66 | * while(true) { |
kenjiArai | 1:102230f2879d | 67 | * while (fc.status_1pps() == 0) {;} |
kenjiArai | 1:102230f2879d | 68 | * counter_1pps = fc.read_avarage_1pps(); |
kenjiArai | 1:102230f2879d | 69 | * while (fc.status_freq_update() == 0) {;} |
kenjiArai | 1:102230f2879d | 70 | * new_frequency = fc.read_freq_data(); |
kenjiArai | 4:9d3b3f0a3882 | 71 | * printf("1PPS/ave = %9d , FREQUENCY = %11.3f\r\n", counter_1pps, new_frequency); |
kenjiArai | 1:102230f2879d | 72 | * } |
kenjiArai | 1:102230f2879d | 73 | * } |
kenjiArai | 1:102230f2879d | 74 | * @endcode |
kenjiArai | 1:102230f2879d | 75 | */ |
kenjiArai | 1:102230f2879d | 76 | |
kenjiArai | 1:102230f2879d | 77 | class FRQ_CUNTR |
kenjiArai | 1:102230f2879d | 78 | { |
kenjiArai | 1:102230f2879d | 79 | public: |
kenjiArai | 2:194f82ad3041 | 80 | |
kenjiArai | 1:102230f2879d | 81 | /** Configure data pin (Not changeable) |
kenjiArai | 2:194f82ad3041 | 82 | * @param Freq. input pin + Gate time[sec] + External clock[MHz] |
kenjiArai | 1:102230f2879d | 83 | */ |
kenjiArai | 2:194f82ad3041 | 84 | FRQ_CUNTR(PinName f_in, double gt, double ex_clock); |
kenjiArai | 1:102230f2879d | 85 | |
kenjiArai | 1:102230f2879d | 86 | /** Set gate time |
kenjiArai | 1:102230f2879d | 87 | * @param gate time [sec] |
kenjiArai | 2:194f82ad3041 | 88 | * @return gate time (range 50mS to 1 minute) |
kenjiArai | 1:102230f2879d | 89 | */ |
kenjiArai | 1:102230f2879d | 90 | double set_gate_time(double gt); |
kenjiArai | 1:102230f2879d | 91 | |
kenjiArai | 4:9d3b3f0a3882 | 92 | /** Set external clock frequency |
kenjiArai | 4:9d3b3f0a3882 | 93 | * @param frequency e.g. 25.000000 [MHz] |
kenjiArai | 4:9d3b3f0a3882 | 94 | * @return none |
kenjiArai | 4:9d3b3f0a3882 | 95 | */ |
kenjiArai | 4:9d3b3f0a3882 | 96 | void set_external_clock(double ex_clock); |
kenjiArai | 4:9d3b3f0a3882 | 97 | |
kenjiArai | 2:194f82ad3041 | 98 | /** Read gate time |
kenjiArai | 2:194f82ad3041 | 99 | * @param none |
kenjiArai | 2:194f82ad3041 | 100 | * @return gate time (range 50mS to 1 minute) |
kenjiArai | 2:194f82ad3041 | 101 | */ |
kenjiArai | 2:194f82ad3041 | 102 | double read_gate_time(void); |
kenjiArai | 2:194f82ad3041 | 103 | |
kenjiArai | 1:102230f2879d | 104 | /** Read status (new frequency data is available or not) |
kenjiArai | 1:102230f2879d | 105 | * @param none |
kenjiArai | 1:102230f2879d | 106 | * @return !=0: new data is avairable, 0: not yet |
kenjiArai | 1:102230f2879d | 107 | */ |
kenjiArai | 1:102230f2879d | 108 | uint32_t status_freq_update(void); |
kenjiArai | 1:102230f2879d | 109 | |
kenjiArai | 1:102230f2879d | 110 | /** Read new frequency data |
kenjiArai | 1:102230f2879d | 111 | * @param none |
kenjiArai | 1:102230f2879d | 112 | * @return frequency data |
kenjiArai | 1:102230f2879d | 113 | */ |
kenjiArai | 2:194f82ad3041 | 114 | double read_freq_data(void); |
kenjiArai | 0:bfdc6ed58a06 | 115 | |
kenjiArai | 1:102230f2879d | 116 | /** Read avarage measued data GPS 1PPS |
kenjiArai | 1:102230f2879d | 117 | * @param none |
kenjiArai | 1:102230f2879d | 118 | * @return Frequency |
kenjiArai | 1:102230f2879d | 119 | */ |
kenjiArai | 1:102230f2879d | 120 | uint32_t read_avarage_1pps(void); |
kenjiArai | 1:102230f2879d | 121 | |
kenjiArai | 4:9d3b3f0a3882 | 122 | /** Read newest measued data GPS 1PPS |
kenjiArai | 4:9d3b3f0a3882 | 123 | * @param none |
kenjiArai | 4:9d3b3f0a3882 | 124 | * @return Frequency |
kenjiArai | 4:9d3b3f0a3882 | 125 | */ |
kenjiArai | 4:9d3b3f0a3882 | 126 | uint32_t read_newest_1pps(void); |
kenjiArai | 4:9d3b3f0a3882 | 127 | |
kenjiArai | 1:102230f2879d | 128 | /** Read status (new 1PPS data is available or not) |
kenjiArai | 1:102230f2879d | 129 | * @param none |
kenjiArai | 1:102230f2879d | 130 | * @return !=0: new data is avairable, 0: not yet |
kenjiArai | 1:102230f2879d | 131 | */ |
kenjiArai | 1:102230f2879d | 132 | uint32_t status_1pps(void); |
kenjiArai | 1:102230f2879d | 133 | |
kenjiArai | 2:194f82ad3041 | 134 | /** Read GPS status |
kenjiArai | 2:194f82ad3041 | 135 | * @param none |
kenjiArai | 2:194f82ad3041 | 136 | * @return 1: GPS is ready |
kenjiArai | 2:194f82ad3041 | 137 | */ |
kenjiArai | 3:339307e1dc0d | 138 | uint8_t status_gps(void); |
kenjiArai | 2:194f82ad3041 | 139 | |
kenjiArai | 2:194f82ad3041 | 140 | /** This is a "TEST PURPOSE" function |
kenjiArai | 1:102230f2879d | 141 | * Check PA0 pin input or internal clock frequency |
kenjiArai | 1:102230f2879d | 142 | * @param none |
kenjiArai | 1:102230f2879d | 143 | * @return Frequency |
kenjiArai | 1:102230f2879d | 144 | */ |
kenjiArai | 1:102230f2879d | 145 | uint32_t read_frequency_TIM2(float gate_time); |
kenjiArai | 1:102230f2879d | 146 | |
kenjiArai | 2:194f82ad3041 | 147 | /** This is a "TEST PURPOSE" function |
kenjiArai | 1:102230f2879d | 148 | * Check PC6 pin input frequency |
kenjiArai | 1:102230f2879d | 149 | * @param none |
kenjiArai | 1:102230f2879d | 150 | * @return Frequency |
kenjiArai | 1:102230f2879d | 151 | */ |
kenjiArai | 1:102230f2879d | 152 | uint32_t read_frequency_TIM3P4(float gate_time); |
kenjiArai | 1:102230f2879d | 153 | |
kenjiArai | 2:194f82ad3041 | 154 | /** This is a "TEST PURPOSE" function |
kenjiArai | 1:102230f2879d | 155 | * Output clock from pin PA8 & PC9 uses for MCO_1 & MCO_2 |
kenjiArai | 1:102230f2879d | 156 | * @param none |
kenjiArai | 1:102230f2879d | 157 | * @return none |
kenjiArai | 1:102230f2879d | 158 | */ |
kenjiArai | 1:102230f2879d | 159 | void port_mco1_mco2_set(uint8_t select); |
kenjiArai | 1:102230f2879d | 160 | |
kenjiArai | 2:194f82ad3041 | 161 | /** This is a "DEBUG PURPOSE" function |
kenjiArai | 2:194f82ad3041 | 162 | * print internal data (need to define "DEBUG" |
kenjiArai | 2:194f82ad3041 | 163 | * @param none |
kenjiArai | 2:194f82ad3041 | 164 | * @return none |
kenjiArai | 2:194f82ad3041 | 165 | */ |
kenjiArai | 2:194f82ad3041 | 166 | void debug_printf_internal_data(void); |
kenjiArai | 2:194f82ad3041 | 167 | |
kenjiArai | 1:102230f2879d | 168 | protected: |
kenjiArai | 1:102230f2879d | 169 | DigitalIn _pin; |
kenjiArai | 1:102230f2879d | 170 | |
kenjiArai | 1:102230f2879d | 171 | void initialize_Freq_counter(void); // Initialize timers |
kenjiArai | 2:194f82ad3041 | 172 | // Internal clock (100MHz) or External clock(?MHz) and IC2 for GPS 1pps signal measurement |
kenjiArai | 1:102230f2879d | 173 | void initialize_TIM2(void); |
kenjiArai | 1:102230f2879d | 174 | // Initialize TIM3 and TIM4 as 32bit counter (TIM3(16bit) + TIM4(16bit)) |
kenjiArai | 1:102230f2879d | 175 | void initialize_TIM3P4(void); |
kenjiArai | 1:102230f2879d | 176 | uint32_t set_1PPS_data(void); // Set GPS 1PPS counter value |
kenjiArai | 1:102230f2879d | 177 | uint32_t read_ic2_counter_TIM2(void); // Read TIM2 captured counter value |
kenjiArai | 1:102230f2879d | 178 | uint32_t check_ic2_status_TIM2(void); // Check TIM2 IC2 status |
kenjiArai | 1:102230f2879d | 179 | uint32_t read_ic2_counter_TIM3P4(void); // Read TIM3+4(as 32bit) captured counter value |
kenjiArai | 1:102230f2879d | 180 | uint32_t check_ic2_status_TIM3P4(void); // Check TIM3 IC2 & TIM4 IC1 status |
kenjiArai | 1:102230f2879d | 181 | uint8_t read_oc_port_status(void); // Check TIM2 OC port |
kenjiArai | 1:102230f2879d | 182 | |
kenjiArai | 1:102230f2879d | 183 | private: |
kenjiArai | 2:194f82ad3041 | 184 | double newest_frequency; |
kenjiArai | 2:194f82ad3041 | 185 | double gate_time; |
kenjiArai | 2:194f82ad3041 | 186 | double ex_clock_freq; |
kenjiArai | 2:194f82ad3041 | 187 | uint32_t ex_clk_base; |
kenjiArai | 2:194f82ad3041 | 188 | uint32_t clk_hi_const; |
kenjiArai | 2:194f82ad3041 | 189 | uint32_t clk_upper_limit; |
kenjiArai | 2:194f82ad3041 | 190 | uint32_t clk_lower_limit; |
kenjiArai | 3:339307e1dc0d | 191 | uint8_t gps_ready; |
kenjiArai | 1:102230f2879d | 192 | // TIM2 |
kenjiArai | 1:102230f2879d | 193 | uint32_t counter_tim2; |
kenjiArai | 1:102230f2879d | 194 | uint32_t old_cntr_tim2; |
kenjiArai | 1:102230f2879d | 195 | // TIM3+4 |
kenjiArai | 1:102230f2879d | 196 | uint32_t counter_tim3p4; |
kenjiArai | 1:102230f2879d | 197 | uint32_t old_cntr_tim3p4; |
kenjiArai | 1:102230f2879d | 198 | // 1PPS data |
kenjiArai | 1:102230f2879d | 199 | uint32_t onepps_newest; |
kenjiArai | 1:102230f2879d | 200 | uint32_t onepps_cnt[CNT_BF_SIZE]; |
kenjiArai | 1:102230f2879d | 201 | uint32_t onepps_num; |
kenjiArai | 1:102230f2879d | 202 | uint64_t onepps_cnt_avarage; |
kenjiArai | 1:102230f2879d | 203 | uint8_t onepps_buf_full; |
kenjiArai | 1:102230f2879d | 204 | uint8_t onepps_ready_flg; |
kenjiArai | 2:194f82ad3041 | 205 | |
kenjiArai | 1:102230f2879d | 206 | }; |
kenjiArai | 1:102230f2879d | 207 | |
kenjiArai | 1:102230f2879d | 208 | /* |
kenjiArai | 1:102230f2879d | 209 | Interrupt handler does NOT work following code |
kenjiArai | 1:102230f2879d | 210 | NVIC_SetVector(TIM2_IRQn, (uint32_t)FRQ_CUNTR::irq_ic2_TIM2); |
kenjiArai | 1:102230f2879d | 211 | From this reason, I wrote below code and set interrupt handler out side "FRQ_CUNTR" class |
kenjiArai | 1:102230f2879d | 212 | NVIC_SetVector(TIM2_IRQn, (uint32_t)irq_ic2_TIM2); |
kenjiArai | 1:102230f2879d | 213 | */ |
kenjiArai | 1:102230f2879d | 214 | void irq_ic2_TIM2(void); // TIM2 IC2 Interrupt control |
kenjiArai | 1:102230f2879d | 215 | void irq_ic2_TIM3P4(void); // TIM3 IC2 Interrupt control (same signal connected to TIM4 IC1) |
kenjiArai | 1:102230f2879d | 216 | |
kenjiArai | 0:bfdc6ed58a06 | 217 | } // Frequency_counter |
kenjiArai | 0:bfdc6ed58a06 | 218 | |
kenjiArai | 1:102230f2879d | 219 | #endif // MBED_FRQ_CUNTR |