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@1:102230f2879d, 2014-11-22 (annotated)
- Committer:
- kenjiArai
- Date:
- Sat Nov 22 23:02:39 2014 +0000
- Revision:
- 1:102230f2879d
- Parent:
- 0:bfdc6ed58a06
- Child:
- 2:194f82ad3041
Created library interface functions. Hardware related parts are almost done.
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 | 1:102230f2879d | 11 | * Revised: Nobember 23rd, 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 | 1:102230f2879d | 25 | #define DEBUG // use Communication with PC(UART) |
kenjiArai | 1:102230f2879d | 26 | /* |
kenjiArai | 1:102230f2879d | 27 | CAUTION: |
kenjiArai | 1:102230f2879d | 28 | If you select internal clock (100MHz), you need consider PLL clock behavior. |
kenjiArai | 1:102230f2879d | 29 | PLL clock drifts over 60Hz (increase frequency) within 30 to 40 second |
kenjiArai | 1:102230f2879d | 30 | then suddenly back to low frequency and increase again. |
kenjiArai | 1:102230f2879d | 31 | Even you prepare precision external clock, this frequency drift cannot avoid. |
kenjiArai | 1:102230f2879d | 32 | */ |
kenjiArai | 1:102230f2879d | 33 | #define BASE_EXTERNAL_CLOCK |
kenjiArai | 1:102230f2879d | 34 | |
kenjiArai | 0:bfdc6ed58a06 | 35 | namespace Frequency_counter |
kenjiArai | 0:bfdc6ed58a06 | 36 | { |
kenjiArai | 1:102230f2879d | 37 | #define CNT_BASE 29999978 // 30MHz |
kenjiArai | 1:102230f2879d | 38 | #define CNT_FIX_BASE 600000 // 0.03sec |
kenjiArai | 1:102230f2879d | 39 | |
kenjiArai | 1:102230f2879d | 40 | #if defined(BASE_EXTERNAL_CLOCK) |
kenjiArai | 1:102230f2879d | 41 | #define CNT_UPPER (CNT_BASE + 20) |
kenjiArai | 1:102230f2879d | 42 | #define CNT_LOWER (CNT_BASE - 20) |
kenjiArai | 1:102230f2879d | 43 | #else |
kenjiArai | 1:102230f2879d | 44 | #define CNT_UPPER (0xffffffff - 100) |
kenjiArai | 1:102230f2879d | 45 | #define CNT_LOWER (0 + 100) |
kenjiArai | 1:102230f2879d | 46 | #endif |
kenjiArai | 1:102230f2879d | 47 | |
kenjiArai | 1:102230f2879d | 48 | #if defined(BASE_EXTERNAL_CLOCK) |
kenjiArai | 1:102230f2879d | 49 | #define ONE_SECOND_COUNT (CNT_BASE - CNT_FIX_BASE) |
kenjiArai | 1:102230f2879d | 50 | #else |
kenjiArai | 1:102230f2879d | 51 | #define ONE_SECOND_COUNT 0x2faf080 // 50MHz |
kenjiArai | 1:102230f2879d | 52 | #endif |
kenjiArai | 1:102230f2879d | 53 | |
kenjiArai | 1:102230f2879d | 54 | #define CNT_BF_SIZE 120 // 1PPS data save size |
kenjiArai | 1:102230f2879d | 55 | |
kenjiArai | 1:102230f2879d | 56 | /** Frequency Counter program |
kenjiArai | 1:102230f2879d | 57 | * Only for ST Nucleo F411RE Board |
kenjiArai | 1:102230f2879d | 58 | * |
kenjiArai | 1:102230f2879d | 59 | * @code |
kenjiArai | 1:102230f2879d | 60 | * #include "mbed.h" |
kenjiArai | 1:102230f2879d | 61 | * |
kenjiArai | 1:102230f2879d | 62 | * // PC_6,PC_7 & PB6 use for Timer3 & 4(16+16bit) |
kenjiArai | 1:102230f2879d | 63 | * // PA_0,PA_1 & PB10 use for Timer2(32bit) |
kenjiArai | 1:102230f2879d | 64 | * FRQ_CUNTR fc(PC_6, 1.0); // Input port(Fixed) & gate time[sec] |
kenjiArai | 1:102230f2879d | 65 | * |
kenjiArai | 1:102230f2879d | 66 | * int main() { |
kenjiArai | 1:102230f2879d | 67 | * // This is for test purpose |
kenjiArai | 1:102230f2879d | 68 | * fc.port_mco1_mco2_set(2); // Clk/2 ->1/1(100MHz) cannot measure!! |
kenjiArai | 1:102230f2879d | 69 | * fc.read_frequency_TIM2(1.0); // read TIM2 source frequency (test) |
kenjiArai | 1:102230f2879d | 70 | * fc.read_frequency_TIM3P4(1.0); // read TIM3 source frequency (test) |
kenjiArai | 1:102230f2879d | 71 | * while(true) { |
kenjiArai | 1:102230f2879d | 72 | * while (fc.status_1pps() == 0) {;} |
kenjiArai | 1:102230f2879d | 73 | * counter_1pps = fc.read_avarage_1pps(); |
kenjiArai | 1:102230f2879d | 74 | * while (fc.status_freq_update() == 0) {;} |
kenjiArai | 1:102230f2879d | 75 | * new_frequency = fc.read_freq_data(); |
kenjiArai | 1:102230f2879d | 76 | * print("1PPS/ave = %9d , FREQUENCY = %9d\r\n", counter_1pps, new_frequency); |
kenjiArai | 1:102230f2879d | 77 | * } |
kenjiArai | 1:102230f2879d | 78 | * } |
kenjiArai | 1:102230f2879d | 79 | * @endcode |
kenjiArai | 1:102230f2879d | 80 | */ |
kenjiArai | 1:102230f2879d | 81 | |
kenjiArai | 1:102230f2879d | 82 | class FRQ_CUNTR |
kenjiArai | 1:102230f2879d | 83 | { |
kenjiArai | 1:102230f2879d | 84 | public: |
kenjiArai | 1:102230f2879d | 85 | /** Configure data pin (Not changeable) |
kenjiArai | 1:102230f2879d | 86 | * @param Freq. input pin |
kenjiArai | 1:102230f2879d | 87 | */ |
kenjiArai | 1:102230f2879d | 88 | FRQ_CUNTR(PinName f_in, double gt); |
kenjiArai | 1:102230f2879d | 89 | |
kenjiArai | 1:102230f2879d | 90 | /** Set gate time |
kenjiArai | 1:102230f2879d | 91 | * @param gate time [sec] |
kenjiArai | 1:102230f2879d | 92 | * @return !=0: new data is avairable, 0: not yet |
kenjiArai | 1:102230f2879d | 93 | */ |
kenjiArai | 1:102230f2879d | 94 | double set_gate_time(double gt); |
kenjiArai | 1:102230f2879d | 95 | |
kenjiArai | 1:102230f2879d | 96 | /** Read status (new frequency data is available or not) |
kenjiArai | 1:102230f2879d | 97 | * @param none |
kenjiArai | 1:102230f2879d | 98 | * @return !=0: new data is avairable, 0: not yet |
kenjiArai | 1:102230f2879d | 99 | */ |
kenjiArai | 1:102230f2879d | 100 | uint32_t status_freq_update(void); |
kenjiArai | 1:102230f2879d | 101 | |
kenjiArai | 1:102230f2879d | 102 | /** Read new frequency data |
kenjiArai | 1:102230f2879d | 103 | * @param none |
kenjiArai | 1:102230f2879d | 104 | * @return frequency data |
kenjiArai | 1:102230f2879d | 105 | */ |
kenjiArai | 1:102230f2879d | 106 | uint32_t read_freq_data(void); |
kenjiArai | 0:bfdc6ed58a06 | 107 | |
kenjiArai | 1:102230f2879d | 108 | /** Read avarage measued data GPS 1PPS |
kenjiArai | 1:102230f2879d | 109 | * @param none |
kenjiArai | 1:102230f2879d | 110 | * @return Frequency |
kenjiArai | 1:102230f2879d | 111 | */ |
kenjiArai | 1:102230f2879d | 112 | uint32_t read_avarage_1pps(void); |
kenjiArai | 1:102230f2879d | 113 | |
kenjiArai | 1:102230f2879d | 114 | /** Read status (new 1PPS data is available or not) |
kenjiArai | 1:102230f2879d | 115 | * @param none |
kenjiArai | 1:102230f2879d | 116 | * @return !=0: new data is avairable, 0: not yet |
kenjiArai | 1:102230f2879d | 117 | */ |
kenjiArai | 1:102230f2879d | 118 | uint32_t status_1pps(void); |
kenjiArai | 1:102230f2879d | 119 | |
kenjiArai | 1:102230f2879d | 120 | /** This is a test purpose function |
kenjiArai | 1:102230f2879d | 121 | * Check PA0 pin input or internal clock frequency |
kenjiArai | 1:102230f2879d | 122 | * @param none |
kenjiArai | 1:102230f2879d | 123 | * @return Frequency |
kenjiArai | 1:102230f2879d | 124 | */ |
kenjiArai | 1:102230f2879d | 125 | uint32_t read_frequency_TIM2(float gate_time); |
kenjiArai | 1:102230f2879d | 126 | |
kenjiArai | 1:102230f2879d | 127 | /** This is a test purpose function |
kenjiArai | 1:102230f2879d | 128 | * Check PC6 pin input frequency |
kenjiArai | 1:102230f2879d | 129 | * @param none |
kenjiArai | 1:102230f2879d | 130 | * @return Frequency |
kenjiArai | 1:102230f2879d | 131 | */ |
kenjiArai | 1:102230f2879d | 132 | uint32_t read_frequency_TIM3P4(float gate_time); |
kenjiArai | 1:102230f2879d | 133 | |
kenjiArai | 1:102230f2879d | 134 | /** This is a test purpose function |
kenjiArai | 1:102230f2879d | 135 | * Output clock from pin PA8 & PC9 uses for MCO_1 & MCO_2 |
kenjiArai | 1:102230f2879d | 136 | * @param none |
kenjiArai | 1:102230f2879d | 137 | * @return none |
kenjiArai | 1:102230f2879d | 138 | */ |
kenjiArai | 1:102230f2879d | 139 | void port_mco1_mco2_set(uint8_t select); |
kenjiArai | 1:102230f2879d | 140 | |
kenjiArai | 1:102230f2879d | 141 | protected: |
kenjiArai | 1:102230f2879d | 142 | DigitalIn _pin; |
kenjiArai | 1:102230f2879d | 143 | |
kenjiArai | 1:102230f2879d | 144 | void initialize_Freq_counter(void); // Initialize timers |
kenjiArai | 1:102230f2879d | 145 | // Internal clock (50MHz) and IC2 for GPS 1pps signal measurement |
kenjiArai | 1:102230f2879d | 146 | void initialize_TIM2(void); |
kenjiArai | 1:102230f2879d | 147 | // Initialize TIM3 and TIM4 as 32bit counter (TIM3(16bit) + TIM4(16bit)) |
kenjiArai | 1:102230f2879d | 148 | void initialize_TIM3P4(void); |
kenjiArai | 1:102230f2879d | 149 | uint32_t set_1PPS_data(void); // Set GPS 1PPS counter value |
kenjiArai | 1:102230f2879d | 150 | uint32_t read_ic2_counter_TIM2(void); // Read TIM2 captured counter value |
kenjiArai | 1:102230f2879d | 151 | uint32_t check_ic2_status_TIM2(void); // Check TIM2 IC2 status |
kenjiArai | 1:102230f2879d | 152 | uint32_t read_ic2_counter_TIM3P4(void); // Read TIM3+4(as 32bit) captured counter value |
kenjiArai | 1:102230f2879d | 153 | uint32_t check_ic2_status_TIM3P4(void); // Check TIM3 IC2 & TIM4 IC1 status |
kenjiArai | 1:102230f2879d | 154 | uint8_t read_oc_port_status(void); // Check TIM2 OC port |
kenjiArai | 1:102230f2879d | 155 | |
kenjiArai | 1:102230f2879d | 156 | private: |
kenjiArai | 1:102230f2879d | 157 | // TIM2 |
kenjiArai | 1:102230f2879d | 158 | double gate_time; |
kenjiArai | 1:102230f2879d | 159 | uint32_t counter_tim2; |
kenjiArai | 1:102230f2879d | 160 | uint32_t old_cntr_tim2; |
kenjiArai | 1:102230f2879d | 161 | // TIM3+4 |
kenjiArai | 1:102230f2879d | 162 | uint32_t counter_tim3p4; |
kenjiArai | 1:102230f2879d | 163 | uint32_t old_cntr_tim3p4; |
kenjiArai | 1:102230f2879d | 164 | // 1PPS data |
kenjiArai | 1:102230f2879d | 165 | uint32_t onepps_newest; |
kenjiArai | 1:102230f2879d | 166 | uint32_t onepps_cnt[CNT_BF_SIZE]; |
kenjiArai | 1:102230f2879d | 167 | uint32_t onepps_num; |
kenjiArai | 1:102230f2879d | 168 | uint64_t onepps_cnt_avarage; |
kenjiArai | 1:102230f2879d | 169 | uint8_t onepps_buf_full; |
kenjiArai | 1:102230f2879d | 170 | uint8_t onepps_ready_flg; |
kenjiArai | 1:102230f2879d | 171 | }; |
kenjiArai | 1:102230f2879d | 172 | |
kenjiArai | 1:102230f2879d | 173 | /* |
kenjiArai | 1:102230f2879d | 174 | Interrupt handler does NOT work following code |
kenjiArai | 1:102230f2879d | 175 | NVIC_SetVector(TIM2_IRQn, (uint32_t)FRQ_CUNTR::irq_ic2_TIM2); |
kenjiArai | 1:102230f2879d | 176 | From this reason, I wrote below code and set interrupt handler out side "FRQ_CUNTR" class |
kenjiArai | 1:102230f2879d | 177 | NVIC_SetVector(TIM2_IRQn, (uint32_t)irq_ic2_TIM2); |
kenjiArai | 1:102230f2879d | 178 | */ |
kenjiArai | 1:102230f2879d | 179 | void irq_ic2_TIM2(void); // TIM2 IC2 Interrupt control |
kenjiArai | 1:102230f2879d | 180 | void irq_ic2_TIM3P4(void); // TIM3 IC2 Interrupt control (same signal connected to TIM4 IC1) |
kenjiArai | 1:102230f2879d | 181 | |
kenjiArai | 0:bfdc6ed58a06 | 182 | } // Frequency_counter |
kenjiArai | 0:bfdc6ed58a06 | 183 | |
kenjiArai | 1:102230f2879d | 184 | #endif // MBED_FRQ_CUNTR |