/***************************************************************************** * * File Name : wm_pwm_demo.c * * Description: pwm demo function * * Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. * All rights reserved. * * Author : dave * * Date : 2014-7-18 *****************************************************************************/ #include #include "wm_include.h" #include "wm_pwm.h" #include "wm_cpu.h" #include "wm_io.h" #include "wm_demo.h" #include "wm_regs.h" #include "wm_dma.h" #include "wm_gpio_afsel.h" #if DEMO_PWM static int pwm_demo_multiplex_config(u8 channel) { switch (channel) { case 0: wm_pwm0_config(WM_IO_PB_00); break; case 1: wm_pwm1_config(WM_IO_PB_01); break; case 2: wm_pwm2_config(WM_IO_PB_02); break; case 3: wm_pwm3_config(WM_IO_PB_03); break; case 4: wm_pwm4_config(WM_IO_PA_07); break; case 5: wm_pwm0_config(WM_IO_PB_19); break; case 6: wm_pwm1_config(WM_IO_PB_20); break; case 7: wm_pwm2_config(WM_IO_PA_00); break; case 8: wm_pwm3_config(WM_IO_PA_01); break; case 9: wm_pwm4_config(WM_IO_PA_04); break; default: break; } return 0; } static int pwm_demo_allsyc_mode(u8 channel,u32 freq, u8 duty, u8 num) { pwm_init_param pwm_param; int ret=-1; tls_sys_clk sysclk; tls_sys_clk_get(&sysclk); memset(&pwm_param, 0, sizeof(pwm_init_param)); pwm_param.period = 255; pwm_param.cnt_type = WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT; pwm_param.loop_type = WM_PWM_LOOP_TYPE_LOOP; pwm_param.mode = WM_PWM_OUT_MODE_ALLSYC; pwm_param.inverse_en = DISABLE; pwm_param.pnum = num; pwm_param.pnum_int = DISABLE; pwm_param.duty = duty; pwm_param.channel = channel; pwm_param.clkdiv = sysclk.apbclk*UNIT_MHZ/256/freq; ret = tls_pwm_out_init(&pwm_param); return ret; } static int pwm_demo_2syc_mode(u8 channel,u32 freq, u8 duty, u8 num) { pwm_init_param pwm_param; int ret=-1; tls_sys_clk sysclk; tls_sys_clk_get(&sysclk); memset(&pwm_param, 0, sizeof(pwm_init_param)); pwm_param.period = 255; pwm_param.cnt_type = WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT; pwm_param.loop_type = WM_PWM_LOOP_TYPE_LOOP; pwm_param.mode = WM_PWM_OUT_MODE_2SYC; pwm_param.inverse_en = DISABLE; pwm_param.pnum = num; pwm_param.pnum_int = DISABLE; pwm_param.duty = duty; pwm_param.channel = channel; pwm_param.clkdiv = sysclk.apbclk*UNIT_MHZ/256/freq; ret = tls_pwm_out_init(&pwm_param); return ret; } static int pwm_demo_mc_mode(u8 channel,u32 freq, u8 duty, u8 num) { pwm_init_param pwm_param; int ret=-1; tls_sys_clk sysclk; tls_sys_clk_get(&sysclk); memset(&pwm_param, 0, sizeof(pwm_init_param)); pwm_param.period = 255; pwm_param.cnt_type = WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT; pwm_param.loop_type = WM_PWM_LOOP_TYPE_LOOP; pwm_param.mode = WM_PWM_OUT_MODE_MC; pwm_param.inverse_en = DISABLE; pwm_param.pnum = num; pwm_param.pnum_int = DISABLE; pwm_param.duty = duty; pwm_param.channel = channel; pwm_param.clkdiv = sysclk.apbclk*UNIT_MHZ/256/freq; pwm_param.dten = ENABLE; pwm_param.dtclkdiv = 3; pwm_param.dtcnt = 255; ret = tls_pwm_out_init(&pwm_param); return ret; } static int pwm_demo_break_mode(u8 channel,u32 freq, u8 duty) { int ret=-1; ret = tls_pwm_brake_mode_config(channel, ENABLE, WM_PWM_BRAKE_OUT_HIGH); return ret; } static void pwm_isr_callback(void) { int fcount=0, rcount=0; int status = tls_reg_read32(HR_PWM_INTSTS); if (status & 0x200) { tls_reg_write32(HR_PWM_INTSTS, tls_reg_read32(HR_PWM_INTSTS) & 0x60); } else { if(status&0x40) //ϽµÑØÖÐ¶Ï { if((status&300) == 0) { fcount=((tls_reg_read32(HR_PWM_CAPDAT)&0xFFFF0000)>>16); } tls_reg_write32(HR_PWM_INTSTS, tls_reg_read32(HR_PWM_INTSTS) & 0x40); printf("fcount = %d\n",fcount); } if(status&0x00000020) //ÉÏÉýÑØÖÐ¶Ï { if((status&0x00000280) == 0) { rcount=(tls_reg_read32(HR_PWM_CAPDAT)&0x0000FFFF); } tls_reg_write32(HR_PWM_INTSTS, tls_reg_read32(HR_PWM_INTSTS) & 0x20); printf("rcount = %d\n",rcount); } } } u32 pwmDmaCap[100]; static void pwm_dma_callback(void) { int i; for(i=0; i<100; i++) { printf("num:%d, pwmH:%d, pwmL:%d\n", i, (pwmDmaCap[i]>>16), (pwmDmaCap[i]&0x0000ffff)); } } void pwm_capture_mode_int(u8 channel,u32 freq) { tls_sys_clk sysclk; tls_sys_clk_get(&sysclk); pwm_demo_multiplex_config(channel); tls_pwm_stop(channel); tls_pwm_isr_register(pwm_isr_callback); tls_pwm_cap_init(channel, sysclk.apbclk*UNIT_MHZ/256/freq, DISABLE, WM_PWM_CAP_RISING_FALLING_EDGE_INT); tls_pwm_start(channel); } void pwm_capture_mode_dma(u8 channel,u32 freq) { u8 dmaCh; struct tls_dma_descriptor DmaDesc; tls_sys_clk sysclk; tls_sys_clk_get(&sysclk); memset(pwmDmaCap, 0, sizeof(pwmDmaCap)/sizeof(char)); pwm_demo_multiplex_config(channel); tls_pwm_stop(channel); dmaCh = tls_dma_request(1, TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_PWM_CAP0) | TLS_DMA_FLAGS_HARD_MODE); DmaDesc.src_addr = HR_PWM_CAPDAT; DmaDesc.dest_addr = (unsigned int)pwmDmaCap; DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_DEST_ADD_INC | TLS_DMA_DESC_CTRL_BURST_SIZE1 | TLS_DMA_DESC_CTRL_DATA_SIZE_WORD | TLS_DMA_DESC_CTRL_TOTAL_BYTES(400); DmaDesc.valid = TLS_DMA_DESC_VALID; DmaDesc.next = NULL; tls_dma_start(dmaCh, &DmaDesc, 0); tls_dma_irq_register(dmaCh, (void (*))pwm_dma_callback, NULL, TLS_DMA_IRQ_TRANSFER_DONE); tls_pwm_cap_init(channel, sysclk.apbclk*UNIT_MHZ/256/freq, DISABLE, WM_PWM_CAP_DMA_INT); tls_pwm_start(channel); } /** * @brief This function is used demonstrate pwm usage. * * @param[in] channel pwm channel, range from 0 to 4 * @param[in] freq freq range from 3Hz~160kHz * @param[in] duty duty range from 0 to 255 * @param[in] mode 0:BRAKE, 1:ALLSYC, 2:2SYC, 3:MC, 4:INDPT * @param[in] pnum period num,range from 0 to 255 * * @retval WM_SUCCESS success * @retval WM_FAILED failed * * @note For example, call this like this "pwm_demo(0,20,99,1,0);". */ int pwm_demo(u8 channel, u16 freq, u8 duty, u8 mode, u8 num) { int ret=-1; u8 channel_used = 0; channel_used = (channel > 4)? (channel - 5):channel; printf("\r\ninput num:%d, channel:%d, freq:%d, duty:%d, mode:%d, num:%d\r\n", channel, channel_used, freq, duty, mode, num); if(channel < 10) { pwm_demo_multiplex_config(channel); tls_pwm_stop(channel_used); } else { return WM_FAILED; } switch (mode) { case WM_PWM_OUT_MODE_INDPT: ret = tls_pwm_init(channel_used, freq, duty, num); if(ret != WM_SUCCESS) return ret; tls_pwm_start(channel_used); break; case WM_PWM_OUT_MODE_ALLSYC: ret = pwm_demo_allsyc_mode(channel_used, freq, duty, num); if(ret != WM_SUCCESS) return ret; tls_pwm_start(channel_used); break; case WM_PWM_OUT_MODE_2SYC: ret = pwm_demo_2syc_mode(channel_used, freq, duty, num); if(ret != WM_SUCCESS) return ret; tls_pwm_start(channel_used); break; case WM_PWM_OUT_MODE_MC: ret = pwm_demo_mc_mode(channel_used, freq, duty, num); if(ret != WM_SUCCESS) return ret; tls_pwm_start(channel_used); break; case WM_PWM_OUT_MODE_BRAKE: ret = pwm_demo_break_mode(channel_used, freq, duty); if(ret != WM_SUCCESS) return ret; tls_pwm_start(channel_used); break; default: break; } return WM_SUCCESS; } #endif