W801_SDK_dev_env/demo/wm_pwm_demo.c
2023-03-08 08:23:45 +01:00

317 lines
8.2 KiB
C
Raw Blame History

/*****************************************************************************
*
* 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 <string.h>
#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) //<2F>½<EFBFBD><C2BD><EFBFBD><EFBFBD>ж<EFBFBD>
{
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) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
{
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