/* * Copyright (c) 2015, Freescale Semiconductor, Inc. * Copyright 2016-2017, 2020 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_debug_console.h" #include "pin_mux.h" #include "board.h" #include "fsl_ftm.h" /******************************************************************************* * Definitions ******************************************************************************/ /* The Flextimer instance/channel used for board */ #define DEMO_FTM_BASEADDR FTM0 /* FTM channel pair used for the dual-edge capture, channel pair 0 uses channels 0 and 1 */ #define BOARD_FTM_INPUT_CAPTURE_CHANNEL_PAIR kFTM_Chnl_0 /* Interrupt number and interrupt handler for the FTM instance used */ #define FTM_INTERRUPT_NUMBER FTM0_IRQn #define FTM_INPUT_CAPTURE_HANDLER FTM0_IRQHandler /* Interrupt to enable and flag to read; depends on the FTM channel used for dual-edge capture */ #define FTM_FIRST_CHANNEL_INTERRUPT_ENABLE kFTM_Chnl0InterruptEnable #define FTM_FIRST_CHANNEL_FLAG kFTM_Chnl0Flag #define FTM_SECOND_CHANNEL_INTERRUPT_ENABLE kFTM_Chnl1InterruptEnable #define FTM_SECOND_CHANNEL_FLAG kFTM_Chnl1Flag /* Get source clock for FTM driver */ #define FTM_SOURCE_CLOCK CLOCK_GetFreq(kCLOCK_BusClk) #define ARR_MAX 100 /******************************************************************************* * Prototypes ******************************************************************************/ /******************************************************************************* * Variables ******************************************************************************/ volatile bool ftmFirstChannelInterruptFlag = false; volatile bool ftmSecondChannelInterruptFlag = false; /* Record FTM TOF interrupt times */ volatile uint32_t g_timerOverflowInterruptCount = 0u; volatile uint32_t g_firstChannelOverflowCount = 0u; volatile uint32_t g_secondChannelOverflowCount = 0u; volatile uint32_t u32_cnt = 0; volatile uint32_t u32_hist1[ARR_MAX]; volatile uint32_t u32_hist2[ARR_MAX]; uint32_t u32_freq[ARR_MAX]; uint32_t u32_temp[ARR_MAX]; uint32_t u32_clkSrc = 0; uint32_t u32_finalFreq = 0; /******************************************************************************* * Code ******************************************************************************/ void FTM_INPUT_CAPTURE_HANDLER(void) { // if (((DEMO_FTM_BASEADDR->STATUS) & FTM_SECOND_CHANNEL_FLAG) == FTM_SECOND_CHANNEL_FLAG) // { DEMO_FTM_BASEADDR->STATUS &= ~(FTM_SECOND_CHANNEL_FLAG & 0xFFU); /* Disable second channel interrupt.*/ if (ARR_MAX > u32_cnt) { // backup CnV, read FTM counter register u32_hist1[u32_cnt] = FTM0->CONTROLS[0].CnV; // backup CnV, read FTM counter register u32_hist2[u32_cnt] = FTM0->CONTROLS[1].CnV; u32_cnt++; } else { NVIC_DisableIRQ(FTM_INTERRUPT_NUMBER); ftmSecondChannelInterruptFlag = true; } // } __DSB(); } /******************************************************************************* need to calculate mean value - but 100 may not enough, need to capture more data ******************************************************************************/ void Freq_Cal(void) { // for debugging purpose u32_clkSrc = FTM_SOURCE_CLOCK; for (uint32_t i = ARR_MAX; i--;) { if (u32_hist1[i] > u32_hist2[i]) { u32_hist2[i] += 0xFFFF; } // calculate the cnt different - get period u32_temp[i] = u32_hist2[i] - u32_hist1[i]; // calculate frequency from period u32_freq[i] = (FTM_SOURCE_CLOCK)/u32_temp[i]; u32_finalFreq += u32_freq[i]; } u32_finalFreq /= ARR_MAX; } /*! * @brief Main function */ int main(void) { ftm_config_t ftmInfo; ftm_dual_edge_capture_param_t edgeParam; uint32_t capture1Val; uint32_t capture2Val; float pulseWidth; uint32_t u32_freq = 0; /* Board pin, clock, debug console init */ BOARD_InitBootPins(); BOARD_InitBootClocks(); BOARD_InitDebugConsole(); #if 1 // set bus clock same as core clock - 120MHz SIM->CLKDIV1 &= 0xF0FFFFFF; #endif /* Print a note to terminal */ PRINTF("\r\nFTM dual-edge capture example\r\n"); PRINTF("\r\nOnce the input signal is received the input capture values are printed"); PRINTF("\r\nThe input signal's pulse width is calculated from the capture values & printed\r\n"); FTM_GetDefaultConfig(&ftmInfo); /* Initialize FTM module */ FTM_Init(DEMO_FTM_BASEADDR, &ftmInfo); edgeParam.mode = kFTM_Continuous; /* Set capture edges to calculate the pulse width of input signal */ edgeParam.currChanEdgeMode = kFTM_RisingEdge; edgeParam.nextChanEdgeMode = kFTM_RisingEdge; /* Setup dual-edge capture on a FTM channel pair */ FTM_SetupDualEdgeCapture(DEMO_FTM_BASEADDR, BOARD_FTM_INPUT_CAPTURE_CHANNEL_PAIR, &edgeParam, 1); /* Set the timer to be in free-running mode */ FTM_SetTimerPeriod(DEMO_FTM_BASEADDR, 0xFFFF); /* Enable first channel interrupt */ //FTM_EnableInterrupts(DEMO_FTM_BASEADDR, FTM_FIRST_CHANNEL_INTERRUPT_ENABLE); /* Enable second channel interrupt when the second edge is detected */ FTM_EnableInterrupts(DEMO_FTM_BASEADDR, FTM_SECOND_CHANNEL_INTERRUPT_ENABLE); /* Enable overflow interrupt */ //FTM_EnableInterrupts(DEMO_FTM_BASEADDR, kFTM_TimeOverflowInterruptEnable); /* Enable at the NVIC */ EnableIRQ(FTM_INTERRUPT_NUMBER); FTM_StartTimer(DEMO_FTM_BASEADDR, kFTM_SystemClock); while (ftmSecondChannelInterruptFlag != true) { } DEMO_FTM_BASEADDR->CONTROLS[0].CnSC &= ~FTM_CnSC_CHIE_MASK; DEMO_FTM_BASEADDR->COMBINE &= 0xFFFFFFFB; Freq_Cal(); /* Clear first channel interrupt flag after the second edge is detected.*/ FTM_ClearStatusFlags(DEMO_FTM_BASEADDR, FTM_FIRST_CHANNEL_FLAG); /* Clear overflow interrupt flag.*/ FTM_ClearStatusFlags(DEMO_FTM_BASEADDR, kFTM_TimeOverflowFlag); /* Disable overflow interrupt.*/ FTM_DisableInterrupts(DEMO_FTM_BASEADDR, kFTM_TimeOverflowInterruptEnable); // capture1Val = FTM_GetInputCaptureValue(DEMO_FTM_BASEADDR, (ftm_chnl_t)(BOARD_FTM_INPUT_CAPTURE_CHANNEL_PAIR * 2)); // capture2Val = // FTM_GetInputCaptureValue(DEMO_FTM_BASEADDR, (ftm_chnl_t)(BOARD_FTM_INPUT_CAPTURE_CHANNEL_PAIR * 2 + 1)); // PRINTF("\r\nCapture value C(n)V=%x\r\n", capture1Val); // PRINTF("\r\nCapture value C(n+1)V=%x\r\n", capture2Val); /* FTM clock source is not prescaled and is * divided by 1000000 as the output is printed in microseconds */ // pulseWidth = // (float)(((g_secondChannelOverflowCount - g_firstChannelOverflowCount) * 65536 + capture2Val - capture1Val) + // 1) / // ((float)FTM_SOURCE_CLOCK / 1000000); // PRINTF("\r\nInput signals pulse width = %f us\r\n", pulseWidth); u32_freq = FTM_SOURCE_CLOCK / (capture2Val - capture1Val); while (1) { } }