699 lines
16 KiB
C
Executable File
699 lines
16 KiB
C
Executable File
/*
|
|
* Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the
|
|
* distribution.
|
|
* 3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
|
|
* its contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "cmd_util.h"
|
|
#include "cmd_pwm.h"
|
|
#include "driver/chip/hal_gpio.h"
|
|
#include "driver/chip/hal_pwm.h"
|
|
|
|
typedef enum {
|
|
PWM_COMPLE,
|
|
PWM_PLUSE,
|
|
PWM_CYCLE,
|
|
PWM_CAPTURE,
|
|
PWM_DEADZONE,
|
|
PWM_MODENUM,
|
|
} Cmd_PwmMode;
|
|
|
|
typedef struct {
|
|
uint32_t high_time;
|
|
uint32_t low_time;
|
|
uint16_t num;
|
|
uint16_t count;
|
|
uint8_t d_value;
|
|
uint8_t d_hz;
|
|
uint8_t input_ch;
|
|
uint8_t cap_ch;
|
|
Cmd_PwmMode input_mode;
|
|
} Cmd_Capinfo;
|
|
|
|
static Cmd_Capinfo private_cap[8];
|
|
|
|
static Cmd_PwmMode cmd_pwm_mode_analytic(char *data)
|
|
{
|
|
if (cmd_strcmp(data, "comple") == 0) {
|
|
return PWM_COMPLE;
|
|
} else if (cmd_strcmp(data, "pluse") == 0) {
|
|
return PWM_PLUSE;
|
|
} else if (cmd_strcmp(data, "cycle") == 0) {
|
|
return PWM_CYCLE;
|
|
} else if (cmd_strcmp(data, "capture") == 0) {
|
|
return PWM_CAPTURE;
|
|
} else if (cmd_strcmp(data, "deadzone") == 0) {
|
|
return PWM_DEADZONE;
|
|
}
|
|
return PWM_MODENUM;
|
|
}
|
|
|
|
typedef struct {
|
|
PWM_GROUP_ID group;
|
|
PWM_CH_ID ch;
|
|
} PWM_IoInfo;
|
|
|
|
static int cmd_pwm_init(Cmd_PwmMode mode, PWM_IoInfo info, uint32_t hz)
|
|
{
|
|
HAL_Status ret = HAL_ERROR;
|
|
PWM_ClkParam clk_cfg;
|
|
PWM_CompInitParam comp_cfg;
|
|
PWM_ChInitParam ch_cfg;
|
|
int cycle = 0;
|
|
|
|
clk_cfg.clk = PWM_CLK_HOSC;
|
|
clk_cfg.div = PWM_SRC_CLK_DIV_1;
|
|
|
|
ret = HAL_PWM_GroupClkCfg(info.group, &clk_cfg);
|
|
if (ret != HAL_OK)
|
|
return -1;
|
|
|
|
switch (mode) {
|
|
case PWM_COMPLE:
|
|
comp_cfg.hz = hz;
|
|
comp_cfg.polarity = PWM_HIGHLEVE;
|
|
|
|
cycle = HAL_PWM_ComplementaryInit(info.group, &comp_cfg);
|
|
if (cycle == -1)
|
|
return -1;
|
|
|
|
ret = HAL_PWM_ComplementarySetDutyRatio(info.group, cycle / 4);
|
|
if (ret != HAL_OK)
|
|
return -1;
|
|
|
|
break;
|
|
case PWM_CYCLE:
|
|
ch_cfg.hz = hz;
|
|
ch_cfg.mode = PWM_CYCLE_MODE;
|
|
ch_cfg.polarity = PWM_HIGHLEVE;
|
|
|
|
cycle = HAL_PWM_ChInit(info.ch, &ch_cfg);
|
|
if (cycle == -1)
|
|
return -1;
|
|
|
|
ret = HAL_PWM_ChSetDutyRatio(info.ch, cycle / 2);
|
|
if (ret != HAL_OK)
|
|
return -1;
|
|
|
|
break;
|
|
case PWM_PLUSE:
|
|
ch_cfg.hz = hz;
|
|
ch_cfg.mode = PWM_PLUSE_MODE;
|
|
ch_cfg.polarity = PWM_HIGHLEVE;
|
|
|
|
cycle = HAL_PWM_ChInit(info.ch, &ch_cfg);
|
|
if (cycle == -1)
|
|
return -1;
|
|
break;
|
|
case PWM_CAPTURE:
|
|
ch_cfg.hz = hz;
|
|
ch_cfg.mode = PWM_CAPTURE_MODE;
|
|
ch_cfg.polarity = PWM_HIGHLEVE;
|
|
|
|
cycle = HAL_PWM_ChInit(info.ch, &ch_cfg);
|
|
if (cycle == -1)
|
|
return -1;
|
|
|
|
break;
|
|
default:
|
|
CMD_DBG("invalid PWM mode\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PWM_IoInfo cmd_pwm_channel_analytic(Cmd_PwmMode mode, uint32_t channel)
|
|
{
|
|
PWM_IoInfo info;
|
|
if (mode == PWM_COMPLE || mode == PWM_DEADZONE) {
|
|
if (channel > 3) {
|
|
info.ch = PWM_CH_NULL;
|
|
info.group = PWM_GROUP_NULL;
|
|
return info;
|
|
}
|
|
info.group = channel;
|
|
info.ch = PWM_CH_NULL;
|
|
return info;
|
|
} else if (channel > 7) {
|
|
info.ch = PWM_CH_NULL;
|
|
info.group = PWM_GROUP_NULL;
|
|
return info;
|
|
}
|
|
|
|
info.ch = channel;
|
|
info.group = channel / 2;
|
|
|
|
return info;
|
|
}
|
|
|
|
static enum cmd_status cmd_pwm_config_exec(char *cmd)
|
|
{
|
|
uint32_t hz;
|
|
uint32_t channel;
|
|
char mode_char[8];
|
|
int cnt;
|
|
|
|
cnt = cmd_sscanf(cmd, "c=%u m=%s h=%u", &channel, mode_char, &hz);
|
|
|
|
if (cnt != 3) {
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
Cmd_PwmMode mode = cmd_pwm_mode_analytic(mode_char);
|
|
if (mode >= PWM_MODENUM) {
|
|
CMD_ERR("invalid pwm mode %u\n", mode);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
uint32_t mix_freq, max_freq;
|
|
max_freq = HAL_GetHFClock();
|
|
if (max_freq == 24000000)
|
|
mix_freq = 2;
|
|
else if (max_freq == 40000000)
|
|
mix_freq = 3;
|
|
else {
|
|
CMD_ERR("invalid HF\n");
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
if (hz < mix_freq || hz > max_freq) {
|
|
CMD_ERR("pwm hz out of range %u\n", hz);
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
PWM_IoInfo info = cmd_pwm_channel_analytic(mode, channel);
|
|
if (info.group >= PWM_GROUP_NULL)
|
|
return CMD_STATUS_INVALID_ARG;
|
|
|
|
if (cmd_pwm_init(mode, info, hz) == -1)
|
|
return CMD_STATUS_FAIL;
|
|
|
|
return CMD_STATUS_OK;
|
|
}
|
|
|
|
enum cmd_status cmd_pwm_deinit_exec(char *cmd)
|
|
{
|
|
int cnt = 0;
|
|
uint32_t channel;
|
|
char mode_char[8];
|
|
HAL_Status ret = HAL_ERROR;
|
|
|
|
cnt = cmd_sscanf(cmd, "c=%u m=%s", &channel, mode_char);
|
|
if (cnt != 2)
|
|
return CMD_STATUS_INVALID_ARG;
|
|
|
|
Cmd_PwmMode mode = cmd_pwm_mode_analytic(mode_char);
|
|
if (mode >= PWM_MODENUM) {
|
|
CMD_ERR("invalid pwm mode %u\n", mode);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
PWM_IoInfo info = cmd_pwm_channel_analytic(mode, channel);
|
|
if (info.group == PWM_GROUP_NULL) {
|
|
CMD_ERR("invalid pwm channel\n");
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (mode == PWM_COMPLE) {
|
|
ret = HAL_PWM_ComplementaryDeInit(info.group);
|
|
if (ret != HAL_OK)
|
|
return CMD_STATUS_FAIL;
|
|
} else {
|
|
ret = HAL_PWM_ChDeinit(info.ch);
|
|
if (ret != HAL_OK)
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
return CMD_STATUS_OK;
|
|
}
|
|
|
|
enum cmd_status cmd_pwm_start_exec(char *cmd)
|
|
{
|
|
HAL_Status ret;
|
|
char mode_char[8];
|
|
uint32_t channel;
|
|
int cnt;
|
|
|
|
cnt = cmd_sscanf(cmd, "c=%u m=%s", &channel, mode_char);
|
|
if (cnt != 2)
|
|
return CMD_STATUS_INVALID_ARG;
|
|
|
|
Cmd_PwmMode mode = cmd_pwm_mode_analytic(mode_char);
|
|
if (mode >= PWM_MODENUM) {
|
|
CMD_ERR("invalid pwm mode %u\n", mode);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
PWM_IoInfo info = cmd_pwm_channel_analytic(mode, channel);
|
|
if (info.group == PWM_GROUP_NULL) {
|
|
CMD_ERR("invalid pwm channel\n");
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
switch (mode) {
|
|
case PWM_COMPLE:
|
|
ret = HAL_PWM_EnableComplementary(info.group, 1);
|
|
if (ret != HAL_OK) {
|
|
CMD_ERR("Enable comple error\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
break;
|
|
case PWM_PLUSE:
|
|
ret = HAL_PWM_EnableCh(info.ch, PWM_PLUSE_MODE, 1);
|
|
if (ret != HAL_OK) {
|
|
CMD_ERR("Enable channel error\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
cmd_msleep(1);
|
|
ret = HAL_PWM_OutputPluse(info.ch);
|
|
if (ret != HAL_OK) {
|
|
CMD_ERR("start pluse fail, it's busy\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
break;
|
|
case PWM_CYCLE:
|
|
ret = HAL_PWM_EnableCh(info.ch, PWM_CYCLE_MODE, 1);
|
|
if (ret != HAL_OK) {
|
|
CMD_ERR("Enable channel error\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
break;
|
|
case PWM_CAPTURE:
|
|
ret = HAL_PWM_EnableCh(info.ch, PWM_CAPTURE_MODE, 1);
|
|
if (ret != HAL_OK) {
|
|
CMD_ERR("Enable channel error\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
break;
|
|
case PWM_DEADZONE:
|
|
ret = HAL_PWM_EnableDeadZone(info.group, 1);
|
|
if (ret != HAL_OK) {
|
|
CMD_ERR("Enable dead zone error\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
break;
|
|
default:
|
|
CMD_DBG("invalid pwm mode %u\n", mode);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
return CMD_STATUS_OK;
|
|
}
|
|
|
|
enum cmd_status cmd_pwm_set_exec(char *cmd)
|
|
{
|
|
uint32_t value;
|
|
uint32_t channel;
|
|
char function[10];
|
|
int cnt;
|
|
PWM_IoInfo info;
|
|
cnt = cmd_sscanf(cmd, "c=%u m=%s v=%u", &channel, function, &value);
|
|
|
|
if (cnt != 3)
|
|
return CMD_STATUS_INVALID_ARG;
|
|
|
|
if (cmd_strcmp(function, "comple") == 0 ||
|
|
cmd_strcmp(function, "deadzone") == 0)
|
|
info = cmd_pwm_channel_analytic(PWM_COMPLE, channel);
|
|
else
|
|
info = cmd_pwm_channel_analytic(PWM_CYCLE, channel);
|
|
|
|
if (info.group == PWM_GROUP_NULL) {
|
|
CMD_ERR("invalid pwm channel\n");
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (cmd_strcmp(function, "deadzone") == 0) {
|
|
if (value > 255) {
|
|
CMD_ERR("deadzone value out of range\n");
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
HAL_PWM_SetDeadZoneTime(info.group, value);
|
|
} else if (cmd_strcmp(function, "comple") == 0) {
|
|
__IO uint32_t *reg;
|
|
|
|
if (value > 0) {
|
|
info.ch = info.group * 2;
|
|
|
|
reg = &PWM->CH_REG[info.ch].PPR;
|
|
value = value * ((*reg & PWM_PPR_ENTIER_CYCLE) >> 16) / 10000;
|
|
if (value < 1)
|
|
value = 1;
|
|
}
|
|
|
|
HAL_PWM_ComplementarySetDutyRatio(info.group, value);
|
|
} else if (cmd_strcmp(function, "cycle") == 0) {
|
|
__IO uint32_t *reg;
|
|
|
|
if (value > 0) {
|
|
reg = &PWM->CH_REG[info.ch].PPR;
|
|
value = value * ((*reg & PWM_PPR_ENTIER_CYCLE) >> 16) / 10000;
|
|
if (value < 1)
|
|
value = 1;
|
|
}
|
|
HAL_PWM_ChSetDutyRatio(info.ch, value);
|
|
} else if (cmd_strcmp(function, "pluse") == 0) {
|
|
__IO uint32_t *reg;
|
|
|
|
if (value > 0) {
|
|
reg = &PWM->CH_REG[info.ch].PPR;
|
|
value = value * ((*reg & PWM_PPR_ENTIER_CYCLE) >> 16) / 10000;
|
|
if (value < 1)
|
|
value = 1;
|
|
}
|
|
|
|
HAL_PWM_ChSetDutyRatio(info.ch, value);
|
|
|
|
HAL_PWM_EnableCh(info.ch, PWM_PLUSE_MODE, 1);
|
|
} else
|
|
return CMD_STATUS_INVALID_ARG;
|
|
|
|
return CMD_STATUS_OK;
|
|
}
|
|
|
|
|
|
static int PWM_DeadTime(uint8_t chGroup)
|
|
{
|
|
|
|
if (chGroup >= PWM_GROUP_NUM)
|
|
return -1;
|
|
|
|
uint32_t p = PWM->PDZCR[chGroup];
|
|
p &= PWM_CH_DZ_INV;
|
|
return (p >> 8);
|
|
}
|
|
|
|
static int PWM_ReadActCycle(uint8_t ch)
|
|
{
|
|
if (ch >= PWM_CH_NUM)
|
|
return -1;
|
|
int p = (int)PWM->CH_REG[ch].PPR;
|
|
return p;
|
|
}
|
|
|
|
static PWM_Polarity _PWM_Polarity(uint8_t ch)
|
|
{
|
|
if ((PWM->CH_REG[ch].PCR & PWM_PCR_ACT_STA) > 0)
|
|
return PWM_HIGHLEVE;
|
|
|
|
return PWM_LOWLEVE;
|
|
|
|
}
|
|
|
|
static Cmd_PwmMode PWM_ChMode(uint8_t ch)
|
|
{
|
|
__IO uint32_t *reg = NULL;
|
|
reg = &PWM->CH_REG[ch].PCR;
|
|
|
|
if ((*reg & PWM_PCR_MODE) > 0)
|
|
return PWM_PLUSE;
|
|
|
|
return PWM_CYCLE;
|
|
}
|
|
|
|
int PWM_DeadZoneEnable(PWM_GROUP_ID chGroup)
|
|
{
|
|
if (chGroup >= PWM_GROUP_NUM)
|
|
return -1;
|
|
|
|
return PWM->PDZCR[chGroup]&PWM_CH_DZ_EN;
|
|
}
|
|
|
|
void capture_irq(void *arg, PWM_IrqEvent event)
|
|
{
|
|
PWM_CapResult result;
|
|
Cmd_Capinfo *cap_info = (Cmd_Capinfo *)arg;
|
|
|
|
if ((event != PWM_IRQ_RISEEDGE)
|
|
&& (PWM_ChMode(cap_info->input_ch) != PWM_PLUSE))
|
|
return;
|
|
|
|
if (cap_info->count < cap_info->num) {
|
|
if (PWM_ChMode(cap_info->input_ch) == PWM_PLUSE)
|
|
result = HAL_PWM_CaptureResult(PWM_CAP_PLUSE, cap_info->cap_ch);
|
|
else
|
|
result = HAL_PWM_CaptureResult(PWM_CAP_CYCLE, cap_info->cap_ch);
|
|
|
|
if (result.highLevelTime) {
|
|
cap_info->count += 1;
|
|
if ((cap_info->count == 1)
|
|
&& (PWM_ChMode(cap_info->input_ch) != PWM_PLUSE))
|
|
return;
|
|
cap_info->high_time += result.highLevelTime;
|
|
cap_info->low_time += result.lowLevelTime;
|
|
}
|
|
} else
|
|
HAL_PWM_DisableIRQ(cap_info->cap_ch);
|
|
}
|
|
|
|
enum cmd_status cmd_pwm_get_exec(char *cmd)
|
|
{
|
|
uint32_t channel;
|
|
uint32_t src_signal;
|
|
char function[8];
|
|
uint32_t num = 0;
|
|
uint32_t value_deviation = 0;
|
|
uint32_t hz_deviation = 0;
|
|
int cnt;
|
|
HAL_Status ret;
|
|
PWM_IrqParam irq_cfg;
|
|
|
|
cnt = cmd_sscanf(cmd, "c=%u m=%s n=%u input_ch=%u dv=%u dh=%u", &channel,
|
|
function, &num, &src_signal, &value_deviation,
|
|
&hz_deviation);
|
|
if (cnt != 6) {
|
|
CMD_ERR("miss param, %d\n", cnt);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (num > 1000) {
|
|
CMD_ERR("The n value out of range\n");
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (value_deviation > 100 || hz_deviation > 100) {
|
|
CMD_ERR("The value out of range\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
PWM_IoInfo info;
|
|
info = cmd_pwm_channel_analytic(PWM_CYCLE, src_signal);
|
|
if (info.group == PWM_GROUP_NULL) {
|
|
CMD_ERR("invalid src_signal\n");
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
info = cmd_pwm_channel_analytic(PWM_CAPTURE, channel);
|
|
if (info.group == PWM_GROUP_NULL) {
|
|
CMD_ERR("invalid ch \n");
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
Cmd_Capinfo *cap_info = private_cap;
|
|
|
|
cap_info[channel].cap_ch = channel;
|
|
cap_info[channel].num = num + 1;
|
|
cap_info[channel].count = 0;
|
|
cap_info[channel].d_hz = hz_deviation;
|
|
cap_info[channel].d_value = value_deviation;
|
|
cap_info[channel].input_ch = src_signal;
|
|
cap_info[channel].high_time = 0;
|
|
cap_info[channel].low_time = 0;
|
|
cap_info[channel].input_mode = PWM_ChMode(src_signal);
|
|
if (cap_info[channel].input_mode == PWM_PLUSE)
|
|
cap_info[channel].num = num;
|
|
|
|
irq_cfg.arg = &cap_info[channel];
|
|
irq_cfg.callback = capture_irq;
|
|
irq_cfg.event = PWM_IRQ_BOTHEDGE;
|
|
|
|
ret = HAL_PWM_EnableIRQ(channel, &irq_cfg);
|
|
if (ret != HAL_OK) {
|
|
CMD_ERR("Enable irq error\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
return CMD_STATUS_OK;
|
|
}
|
|
|
|
|
|
typedef enum {
|
|
CAP_ERROR,
|
|
CAP_BUSY,
|
|
CAP_OK,
|
|
} CAP_RESULT;
|
|
|
|
CAP_RESULT cmd_CapResult(uint8_t ch)
|
|
{
|
|
CAP_RESULT ret;
|
|
|
|
uint16_t input_right_period = 0, input_right_h_time = 0;
|
|
uint8_t deadzone_time = 0;
|
|
Cmd_Capinfo *info = &private_cap[ch];
|
|
|
|
if (PWM_DeadZoneEnable(info->input_ch/ 2))
|
|
deadzone_time = PWM_DeadTime(info->input_ch / 2);
|
|
|
|
if (info->count == info->num) {
|
|
uint32_t cap_period = 0;
|
|
uint32_t cap_h_time = 0;
|
|
|
|
__IO uint32_t *reg = &PWM->CH_REG[info->input_ch].PPR;
|
|
|
|
input_right_period = (*reg & PWM_PPR_ENTIER_CYCLE) >> 16;
|
|
input_right_h_time = PWM_ReadActCycle(info->input_ch);
|
|
|
|
if (_PWM_Polarity(info->input_ch) == PWM_LOWLEVE)
|
|
input_right_h_time = input_right_period- input_right_h_time;
|
|
|
|
if (deadzone_time > 0) {
|
|
input_right_h_time -= deadzone_time;
|
|
}
|
|
if (PWM_ChMode(info->input_ch) == PWM_CYCLE) {
|
|
cap_h_time = info->high_time / (info->num - 1);
|
|
cap_period = cap_h_time + info->low_time / (info->num - 1);
|
|
|
|
if (abs(cap_h_time - input_right_h_time) <= info->d_value &&
|
|
abs(cap_period - input_right_period) <= info->d_hz)
|
|
ret = CAP_OK;
|
|
else
|
|
ret = CAP_ERROR;
|
|
} else {
|
|
cap_h_time = info->high_time / info->num;
|
|
|
|
if (abs(cap_h_time - input_right_h_time) <= info->d_value)
|
|
ret = CAP_OK;
|
|
else
|
|
ret = CAP_ERROR;
|
|
}
|
|
|
|
memset(info, 0, sizeof(Cmd_Capinfo));
|
|
|
|
return ret;
|
|
}
|
|
|
|
return CAP_BUSY;
|
|
}
|
|
|
|
|
|
enum cmd_status cmd_pwm_get_result_exec(char *cmd)
|
|
{
|
|
uint32_t channel;
|
|
int cnt;
|
|
|
|
cnt = cmd_sscanf(cmd, "c=%u ", &channel);
|
|
if (cnt != 1)
|
|
return CMD_STATUS_INVALID_ARG;
|
|
|
|
PWM_IoInfo info = cmd_pwm_channel_analytic(PWM_CAPTURE, channel);
|
|
|
|
if (info.group == PWM_GROUP_NULL) {
|
|
CMD_ERR("invalid pwm channel\n");
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
CAP_RESULT ret = cmd_CapResult(channel);
|
|
|
|
if (ret == CAP_BUSY) {
|
|
CMD_ERR("PWM%d Capture BUSY\n", info.ch);
|
|
return CMD_STATUS_ERROR_MIN;
|
|
} else if (ret == CAP_ERROR) {
|
|
CMD_ERR("PWM%d Capture ERROR\n", info.ch);
|
|
return CMD_STATUS_FAIL;
|
|
} else if (ret == CAP_OK) {
|
|
return CMD_STATUS_OK;
|
|
}
|
|
|
|
return CMD_STATUS_OK;
|
|
}
|
|
|
|
enum cmd_status cmd_pwm_stop_exec(char *cmd)
|
|
{
|
|
char mode_char[8];
|
|
uint32_t channel;
|
|
int cnt;
|
|
|
|
cnt = cmd_sscanf(cmd, "c=%u m=%s", &channel, mode_char);
|
|
if (cnt != 2)
|
|
return CMD_STATUS_INVALID_ARG;
|
|
|
|
Cmd_PwmMode mode = cmd_pwm_mode_analytic(mode_char);
|
|
if (mode >= PWM_MODENUM) {
|
|
CMD_ERR("invalid pwm mode %u\n", mode);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
PWM_IoInfo info = cmd_pwm_channel_analytic(mode, channel);
|
|
if (info.group == PWM_GROUP_NULL) {
|
|
CMD_ERR("invalid pwm channel\n");
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
|
|
|
|
switch (mode) {
|
|
case PWM_COMPLE:
|
|
HAL_PWM_EnableComplementary(info.group, 0);
|
|
HAL_PWM_SetDeadZoneTime(info.group, 0);
|
|
HAL_PWM_EnableDeadZone(info.group, 0);
|
|
break;
|
|
case PWM_PLUSE:
|
|
HAL_PWM_EnableCh(info.ch, PWM_PLUSE_MODE, 0);
|
|
break;
|
|
case PWM_CYCLE:
|
|
HAL_PWM_EnableCh(info.ch, PWM_CYCLE_MODE, 0);
|
|
break;
|
|
case PWM_CAPTURE:
|
|
HAL_PWM_EnableCh(info.ch, PWM_CAPTURE_MODE, 0);
|
|
HAL_PWM_DisableIRQ(info.ch);
|
|
break;
|
|
case PWM_DEADZONE:
|
|
HAL_PWM_SetDeadZoneTime(info.group, 0);
|
|
HAL_PWM_EnableDeadZone(info.group, 0);
|
|
break;
|
|
default:
|
|
CMD_ERR("invalid pwm mode\n");
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
return CMD_STATUS_OK;
|
|
}
|
|
|
|
/*
|
|
* driver commands
|
|
*/
|
|
static const struct cmd_data g_pwm_cmds[] = {
|
|
{ "deinit", cmd_pwm_deinit_exec },
|
|
{ "config", cmd_pwm_config_exec },
|
|
{ "start", cmd_pwm_start_exec },
|
|
{ "set", cmd_pwm_set_exec },
|
|
{ "get", cmd_pwm_get_exec },
|
|
{ "get_result", cmd_pwm_get_result_exec },
|
|
{ "stop", cmd_pwm_stop_exec },
|
|
};
|
|
|
|
enum cmd_status cmd_pwm_exec(char *cmd)
|
|
{
|
|
return cmd_exec(cmd, g_pwm_cmds, cmd_nitems(g_pwm_cmds));
|
|
}
|
|
|