123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- /**************************************************************************//**
- *
- * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021-02-17 klcheng First version
- *
- ******************************************************************************/
- #include <rtconfig.h>
- #if defined(BSP_USING_PWM_CAPTURE)
- #if ((BSP_USING_PWM0_CAPTURE_CHMSK+BSP_USING_PWM1_CAPTURE_CHMSK)!=0)
- #include <rtdevice.h>
- #include "NuMicro.h"
- /* Private typedef --------------------------------------------------------------*/
- typedef struct nu_capture
- {
- struct rt_inputcapture_device parent;
- PWM_T *pwm;
- uint8_t u8Channel;
- IRQn_Type irq;
- uint32_t u32CurrentRisingCnt;
- uint32_t u32CurrentFallingCnt;
- uint32_t u32LastRisingCnt;
- uint32_t u32LastFallingCnt;
- rt_bool_t input_data_level;
- rt_bool_t pwm_init;
- struct nu_capture *pair;
- } nu_capture_t;
- /* Private functions ------------------------------------------------------------*/
- static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture);
- static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture);
- static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture);
- static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us);
- /* Public functions -------------------------------------------------------------*/
- /* Private variables ------------------------------------------------------------*/
- #if (BSP_USING_PWM0_CAPTURE_CHMSK!=0)
- static const char *nu_pwm0_device_name[PWM_CHANNEL_NUM] = {"pwm0i0", "pwm0i1", "pwm0i2", "pwm0i3", "pwm0i4", "pwm0i5"};
- static nu_capture_t nu_pwm0_capture[PWM_CHANNEL_NUM] = {0};
- #endif
- #if (BSP_USING_PWM1_CAPTURE_CHMSK!=0)
- static const char *nu_pwm1_device_name[PWM_CHANNEL_NUM] = {"pwm1i0", "pwm1i1", "pwm1i2", "pwm1i3", "pwm1i4", "pwm1i5"};
- static nu_capture_t nu_pwm1_capture[PWM_CHANNEL_NUM] = {0};
- #endif
- static struct rt_inputcapture_ops nu_capture_ops =
- {
- .init = nu_capture_init,
- .open = nu_capture_open,
- .close = nu_capture_close,
- .get_pulsewidth = nu_capture_get_pulsewidth,
- };
- /* Functions define ------------------------------------------------------------*/
- static rt_err_t CalPulseWidth(nu_capture_t *nu_capture)
- {
- /* Read the capture counter value if falling/rising edge */
- if (PWM_GetCaptureIntFlag(nu_capture->pwm, nu_capture->u8Channel) == 1)//Rising edge
- {
- PWM_ClearCaptureIntFlag(nu_capture->pwm, nu_capture->u8Channel, PWM_CAPTURE_INT_RISING_LATCH);
- nu_capture->u32CurrentRisingCnt = PWM_GET_CAPTURE_RISING_DATA(nu_capture->pwm, nu_capture->u8Channel);
- }
- else if (PWM_GetCaptureIntFlag(nu_capture->pwm, nu_capture->u8Channel) == 2)//Falling edge
- {
- PWM_ClearCaptureIntFlag(nu_capture->pwm, nu_capture->u8Channel, PWM_CAPTURE_INT_FALLING_LATCH);
- nu_capture->u32CurrentFallingCnt += PWM_GET_CAPTURE_FALLING_DATA(nu_capture->pwm, nu_capture->u8Channel);
- }
- else
- {
- PWM_ClearCaptureIntFlag(nu_capture->pwm, nu_capture->u8Channel, PWM_CAPTURE_INT_RISING_LATCH);
- PWM_ClearCaptureIntFlag(nu_capture->pwm, nu_capture->u8Channel, PWM_CAPTURE_INT_FALLING_LATCH);
- return -(RT_ERROR);
- }
- return RT_EOK;
- }
- #if (BSP_USING_PWM0_CAPTURE_CHMSK!=0)
- void PWM0_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- for (uint8_t i = 0; i < PWM_CHANNEL_NUM ; i++)
- {
- if (PWM_GetCaptureIntFlag(nu_pwm0_capture[i].pwm, nu_pwm0_capture[i].u8Channel) != 0)
- {
- /* Calculate pulse width */
- if (CalPulseWidth(&nu_pwm0_capture[i]) == RT_EOK)
- {
- rt_hw_inputcapture_isr(&nu_pwm0_capture[i].parent, nu_pwm0_capture[i].input_data_level);
- }
- }
- }
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #if (BSP_USING_PWM1_CAPTURE_CHMSK!=0)
- void PWM1_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- for (uint8_t i = 0; i < PWM_CHANNEL_NUM ; i++)
- {
- if (PWM_GetCaptureIntFlag(nu_pwm1_capture[i].pwm, nu_pwm1_capture[i].u8Channel) != 0)
- {
- /* Calculate pulse width */
- if (CalPulseWidth(&nu_pwm1_capture[i]) == RT_EOK)
- {
- rt_hw_inputcapture_isr(&nu_pwm1_capture[i].parent, nu_pwm1_capture[i].input_data_level);
- }
- }
- }
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us)
- {
- rt_err_t ret = RT_EOK;
- nu_capture_t *nu_capture;
- nu_capture = (nu_capture_t *)inputcapture;
- if (nu_capture->u32CurrentFallingCnt)
- {
- if (nu_capture->u32CurrentFallingCnt > nu_capture->u32LastRisingCnt)
- *pulsewidth_us = nu_capture->u32CurrentFallingCnt - nu_capture->u32LastRisingCnt;
- else /* Overrun case */
- *pulsewidth_us = nu_capture->u32CurrentFallingCnt + (0x10000 - nu_capture->u32LastRisingCnt);
- nu_capture->input_data_level = RT_FALSE;
- nu_capture->u32LastFallingCnt = nu_capture->u32CurrentFallingCnt;
- nu_capture->u32CurrentFallingCnt = 0;
- }
- else if (nu_capture->u32CurrentRisingCnt)
- {
- if (nu_capture->u32CurrentRisingCnt > nu_capture->u32LastFallingCnt)
- *pulsewidth_us = nu_capture->u32CurrentRisingCnt - nu_capture->u32LastFallingCnt;
- else /* Overrun case */
- *pulsewidth_us = nu_capture->u32CurrentRisingCnt + (0x10000 - nu_capture->u32LastFallingCnt);
- nu_capture->input_data_level = RT_TRUE;
- nu_capture->u32LastRisingCnt = nu_capture->u32CurrentRisingCnt;
- nu_capture->u32CurrentRisingCnt = 0;
- }
- else
- {
- ret = RT_ERROR;
- }
- return -(ret);
- }
- static rt_err_t nu_pwm_init(nu_capture_t *nu_capture)
- {
- rt_err_t ret = RT_ERROR;
- static rt_bool_t bPWM0Inited = RT_FALSE;
- static rt_bool_t bPWM1Inited = RT_FALSE;
- if (nu_capture->pwm == PWM0)
- {
- if (bPWM0Inited == RT_FALSE)
- {
- /* Enable PWM0 clock */
- SYS_UnlockReg();
- CLK_EnableModuleClock(PWM0_MODULE);
- CLK_SetModuleClock(PWM0_MODULE, CLK_CLKSEL2_PWM0SEL_PCLK0, 0);
- SYS_LockReg();
- bPWM0Inited = RT_TRUE;
- }
- ret = RT_EOK;
- }
- else if (nu_capture->pwm == PWM1)
- {
- if (bPWM1Inited == RT_FALSE)
- {
- /* Enable PWM1 clock */
- SYS_UnlockReg();
- CLK_EnableModuleClock(PWM1_MODULE);
- CLK_SetModuleClock(PWM1_MODULE, CLK_CLKSEL2_PWM1SEL_PCLK1, 0);
- SYS_LockReg();
- bPWM1Inited = RT_TRUE;
- }
- ret = RT_EOK;
- }
- return -(ret);
- }
- static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture)
- {
- rt_err_t ret = RT_EOK;
- nu_capture_t *nu_capture;
- RT_ASSERT(inputcapture != RT_NULL);
- nu_capture = (nu_capture_t *) inputcapture;
- if (nu_pwm_init(nu_capture) != RT_EOK)
- {
- rt_kprintf("Failed to initialize PWM%d.\n", nu_capture->pwm);
- ret = RT_ERROR;
- }
- return -(ret);
- }
- static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture)
- {
- rt_err_t ret = RT_EOK;
- nu_capture_t *nu_capture;
- RT_ASSERT(inputcapture != RT_NULL);
- nu_capture = (nu_capture_t *) inputcapture;
- /* Enable capture rising/falling edge interrupt */
- PWM_EnableCaptureInt(nu_capture->pwm, nu_capture->u8Channel, PWM_CAPTURE_INT_FALLING_LATCH | PWM_CAPTURE_INT_RISING_LATCH);
- /* Enable PWM NVIC interrupt */
- NVIC_EnableIRQ(nu_capture->irq);
- /* Enable Capture Function for PWM */
- PWM_EnableCapture(nu_capture->pwm, 0x1 << nu_capture->u8Channel);
- if ((nu_capture->pwm_init == RT_FALSE) && (nu_capture->pair->pwm_init == RT_FALSE))
- {
- nu_capture->pwm_init = RT_TRUE;
- /* Set capture time as 1000 nanosecond */
- PWM_ConfigCaptureChannel(nu_capture->pwm, nu_capture->u8Channel, 1000, 0);
- /* Set counter type as down count */
- PWM_SET_ALIGNED_TYPE(nu_capture->pwm, 0x1 << nu_capture->u8Channel, PWM_UP_COUNTER);
- /* Enable PWM Timer */
- PWM_Start(nu_capture->pwm, 0x1 << nu_capture->u8Channel);
- }
- return ret;
- }
- static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture)
- {
- rt_err_t ret = RT_EOK;
- nu_capture_t *nu_capture;
- RT_ASSERT(inputcapture != RT_NULL);
- nu_capture = (nu_capture_t *) inputcapture;
- /* Disable capture rising/falling edge interrupt */
- PWM_DisableCaptureInt(nu_capture->pwm, nu_capture->u8Channel, PWM_CAPTURE_INT_FALLING_LATCH | PWM_CAPTURE_INT_RISING_LATCH);
- /* Disable PWM NVIC interrupt */
- NVIC_DisableIRQ(nu_capture->irq);
- /* Enable PWM Timer */
- PWM_Stop(nu_capture->pwm, 0x1 << nu_capture->u8Channel);
- nu_capture->pwm_init = RT_FALSE;
- return ret;
- }
- /* Init and register pwm capture */
- int nu_pwm_capture_device_init(void)
- {
- /* Init PWM0 6 channel and PWM1 6 channel */
- #if (BSP_USING_PWM0_CAPTURE_CHMSK!=0)
- for (int i = 0; i < PWM_CHANNEL_NUM; i++)
- {
- if (BSP_USING_PWM0_CAPTURE_CHMSK & (0x1 << i))
- {
- nu_pwm0_capture[i].pwm = PWM0;
- nu_pwm0_capture[i].u8Channel = i;
- nu_pwm0_capture[i].irq = PWM0_IRQn;
- nu_pwm0_capture[i].u32CurrentRisingCnt = 0;
- nu_pwm0_capture[i].u32CurrentFallingCnt = 0;
- nu_pwm0_capture[i].parent.ops = &nu_capture_ops;
- nu_pwm0_capture[i].pair = &nu_pwm0_capture[((i>>1) << 1) == i? i+1 : i-1];
- nu_pwm0_capture[i].pwm_init = RT_FALSE;
- /* register inputcapture device */
- rt_device_inputcapture_register(&nu_pwm0_capture[i].parent, nu_pwm0_device_name[i], &nu_pwm0_capture[i]);
- }
- }
- #endif //#if (BSP_USING_PWM0_CAPTURE_CHMSK!=0)
- #if (BSP_USING_PWM1_CAPTURE_CHMSK!=0)
- for (int i = 0; i < PWM_CHANNEL_NUM; i++)
- {
- if (BSP_USING_PWM1_CAPTURE_CHMSK & (0x1 << i))
- {
- nu_pwm1_capture[i].pwm = PWM1;
- nu_pwm1_capture[i].u8Channel = i;
- nu_pwm1_capture[i].irq = PWM1_IRQn;
- nu_pwm1_capture[i].u32CurrentRisingCnt = 0;
- nu_pwm1_capture[i].u32CurrentFallingCnt = 0;
- nu_pwm1_capture[i].parent.ops = &nu_capture_ops;
- nu_pwm1_capture[i].pair = &nu_pwm1_capture[((i>>1) << 1) == i? i+1 : i-1];
- nu_pwm1_capture[i].pwm_init = RT_FALSE;
- /* register inputcapture device */
- rt_device_inputcapture_register(&nu_pwm1_capture[i].parent, nu_pwm1_device_name[i], &nu_pwm1_capture[i]);
- }
- }
- #endif //#if (BSP_USING_PWM1_CAPTURE_CHMSK!=0)
- return 0;
- }
- INIT_DEVICE_EXPORT(nu_pwm_capture_device_init);
- #endif //#if ((BSP_USING_PWM0_CAPTURE_CHMSK+BSP_USING_PWM1_CAPTURE_CHMSK)!=0)
- #endif //#if defined(BSP_USING_PWM_CAPTURE)
|