Some checks failed
Basic Checks / license-check (push) Has been cancelled
Basic Checks / include-check (push) Has been cancelled
Basic Checks / style-check (push) Has been cancelled
Basic Checks / docs-check (push) Has been cancelled
Basic Checks / python-tests (push) Has been cancelled
Basic Checks / pin-validation (push) Has been cancelled
Basic Checks / cmake-checks (push) Has been cancelled
Basic Checks / frozen-tools-check (push) Has been cancelled
Publish or Update docker image for head of branch / prepare-tags (push) Has been cancelled
Release or update docker image for a released mbed-os version / prepare-tags (push) Has been cancelled
Publish or Update docker image for head of branch / build-container (push) Has been cancelled
Publish or Update docker image for head of branch / test-container (linux/amd64) (push) Has been cancelled
Publish or Update docker image for head of branch / test-container (linux/arm64) (push) Has been cancelled
Publish or Update docker image for head of branch / deploy-container (push) Has been cancelled
Release or update docker image for a released mbed-os version / build-container (push) Has been cancelled
Release or update docker image for a released mbed-os version / test-container (linux/amd64) (push) Has been cancelled
Release or update docker image for a released mbed-os version / test-container (linux/arm64) (push) Has been cancelled
Release or update docker image for a released mbed-os version / deploy-container (push) Has been cancelled
Prune temporary docker images / prune-images (push) Has been cancelled
591 lines
21 KiB
C
591 lines
21 KiB
C
/*******************************************************************************
|
|
* File Name: cyhal_quaddec.c
|
|
*
|
|
* Description:
|
|
* Provides a high level interface for interacting with the Quadrature Decoder.
|
|
* This is a wrapper around the lower level PDL API.
|
|
*
|
|
********************************************************************************
|
|
* \copyright
|
|
* Copyright 2020-2021 Cypress Semiconductor Corporation
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*******************************************************************************/
|
|
|
|
/**
|
|
* \addtogroup group_hal_impl_quaddec QuadDec (Quadrature Decoder)
|
|
* \ingroup group_hal_impl
|
|
* \{
|
|
* \section section_hal_impl_quaddec_pins Selecting Pins for Quadrature Decoding
|
|
* To identify the pins that are available to use with the Quadrature Decoder, open the PSoC
|
|
* device datasheet and navigate to the 'Multiple Alternate Functions' table. Any pin that has
|
|
* the peri.tr_io_input function can be used.
|
|
*
|
|
* \} group_hal_impl_quaddec
|
|
*/
|
|
|
|
#if defined(COMPONENT_CAT2)
|
|
/**
|
|
* \addtogroup group_hal_impl_quaddec QuadDec (Quadrature Decoder)
|
|
* \ingroup group_hal_impl
|
|
* \{
|
|
* \note The cyhal_quaddec_connect_digital() and cyhal_quaddec_disconnect_digital() functions are
|
|
* not supported with this device and will return a CYHAL_QUADDEC_RSLT_ERR_NOT_SUPPORTED error if
|
|
* it is called. This device does not have the internal circuitry routing that this function is
|
|
* used to configure.
|
|
*
|
|
* \} group_hal_impl_quaddec
|
|
*/
|
|
#endif
|
|
|
|
#include "cy_tcpwm.h"
|
|
#include "cy_tcpwm_quaddec.h"
|
|
#include "cyhal_clock.h"
|
|
#include "cyhal_gpio.h"
|
|
#include "cyhal_hwmgr.h"
|
|
#include "cyhal_interconnect.h"
|
|
#include "cyhal_quaddec.h"
|
|
#include "cyhal_syspm.h"
|
|
#include "cyhal_tcpwm_common.h"
|
|
#include "cyhal_utils.h"
|
|
|
|
#include <string.h>
|
|
|
|
#if defined(__cplusplus)
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define _CYHAL_CNT_NUM _CYHAL_TCPWM_CNT_NUMBER(obj->tcpwm.resource)
|
|
|
|
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
|
|
static cyhal_tcpwm_input_t _cyhal_quaddec_translate_input_signal(cyhal_quaddec_input_t signal);
|
|
#endif
|
|
|
|
static inline cy_rslt_t _cyhal_quaddec_configure_clock(cyhal_tcpwm_t *tcpwm, en_clk_dst_t pclk, uint32_t frequency)
|
|
{
|
|
cy_rslt_t rslt;
|
|
|
|
const cyhal_clock_tolerance_t tolerance = {
|
|
.type = CYHAL_TOLERANCE_PERCENT,
|
|
.value = 2,
|
|
};
|
|
|
|
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
|
|
rslt = _cyhal_utils_allocate_clock(&tcpwm->clock, &tcpwm->resource, CYHAL_CLOCK_BLOCK_PERIPHERAL_16BIT, true);
|
|
#elif defined(COMPONENT_CAT2)
|
|
rslt = cyhal_clock_allocate(&tcpwm->clock, CYHAL_CLOCK_BLOCK_PERIPHERAL_16BIT);
|
|
#endif
|
|
|
|
if (rslt == CY_RSLT_SUCCESS)
|
|
{
|
|
tcpwm->dedicated_clock = true;
|
|
|
|
if (cyhal_clock_set_frequency(&tcpwm->clock, frequency, &tolerance) == CY_RSLT_SUCCESS)
|
|
{
|
|
if (Cy_SysClk_PeriphAssignDivider(pclk, (cy_en_divider_types_t)tcpwm->clock.block, tcpwm->clock.channel) ==
|
|
CY_SYSCLK_SUCCESS)
|
|
{
|
|
cyhal_clock_set_enabled(&tcpwm->clock, true, false);
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
return CYHAL_QUADDEC_RSLT_ERR_CLOCK_INIT;
|
|
}
|
|
|
|
#if defined(COMPONENT_CAT2)
|
|
//--------------------------------------------------------------------------------------------------
|
|
// _cyhal_quaddec_connect_pin
|
|
//
|
|
// NOTE: This function should be called after the pin has been initialized with cyhal_gpio_init().
|
|
//--------------------------------------------------------------------------------------------------
|
|
cy_rslt_t _cyhal_quaddec_connect_pin(cyhal_quaddec_input_t signal, cyhal_gpio_t pin,
|
|
TCPWM_Type* base, uint8_t channel_num)
|
|
{
|
|
#if defined(CYHAL_PIN_MAP_TCPWM_TR_IN)
|
|
bool found = false;
|
|
uint8_t index;
|
|
uint8_t array_size = sizeof(cyhal_pin_map_tcpwm_tr_in) / sizeof(cyhal_resource_pin_mapping_t);
|
|
cyhal_resource_pin_mapping_t mapping;
|
|
|
|
// Search through cyhal_pin_map_tcpwm_tr_in to determine if pin can be
|
|
// used to drive a trigger line.
|
|
for (index = 0; index < array_size; index++)
|
|
{
|
|
mapping = cyhal_pin_map_tcpwm_tr_in[index];
|
|
|
|
if (mapping.pin == pin)
|
|
{
|
|
found = true;
|
|
Cy_GPIO_SetHSIOM(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), mapping.hsiom);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found)
|
|
{
|
|
return CYHAL_GPIO_RSLT_ERR_NO_OUTPUT_SIGNAL;
|
|
}
|
|
|
|
switch (signal)
|
|
{
|
|
case CYHAL_QUADDEC_INPUT_PHI_A:
|
|
TCPWM_CNT_TR_CTRL0(base, channel_num) &= ~TCPWM_CNT_TR_CTRL0_COUNT_SEL_Msk;
|
|
TCPWM_CNT_TR_CTRL0(base, channel_num) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_COUNT_SEL,
|
|
(uint32_t)(mapping.inst) + 2);
|
|
TCPWM_CNT_TR_CTRL1(base, channel_num) &= ~TCPWM_CNT_TR_CTRL1_COUNT_EDGE_Msk;
|
|
TCPWM_CNT_TR_CTRL1(base, channel_num) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_COUNT_EDGE,
|
|
CYHAL_EDGE_TYPE_RISING_EDGE);
|
|
break;
|
|
|
|
case CYHAL_QUADDEC_INPUT_PHI_B:
|
|
TCPWM_CNT_TR_CTRL0(base, channel_num) &= ~TCPWM_CNT_TR_CTRL0_START_SEL_Msk;
|
|
TCPWM_CNT_TR_CTRL0(base, channel_num) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_START_SEL,
|
|
(uint32_t)(mapping.inst) + 2);
|
|
TCPWM_CNT_TR_CTRL1(base, channel_num) &= ~TCPWM_CNT_TR_CTRL1_START_EDGE_Msk;
|
|
TCPWM_CNT_TR_CTRL1(base, channel_num) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_START_EDGE,
|
|
CYHAL_EDGE_TYPE_RISING_EDGE);
|
|
break;
|
|
|
|
case CYHAL_QUADDEC_INPUT_INDEX:
|
|
TCPWM_CNT_TR_CTRL0(base, channel_num) &= ~TCPWM_CNT_TR_CTRL0_RELOAD_SEL_Msk;
|
|
TCPWM_CNT_TR_CTRL0(base, channel_num) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_RELOAD_SEL,
|
|
(uint32_t)(mapping.inst) + 2);
|
|
TCPWM_CNT_TR_CTRL1(base, channel_num) &= ~TCPWM_CNT_TR_CTRL1_RELOAD_EDGE_Msk;
|
|
TCPWM_CNT_TR_CTRL1(base, channel_num) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_RELOAD_EDGE,
|
|
CYHAL_EDGE_TYPE_RISING_EDGE);
|
|
break;
|
|
|
|
default:
|
|
return CYHAL_GPIO_RSLT_ERR_NO_OUTPUT_SIGNAL;
|
|
}
|
|
|
|
return CY_RSLT_SUCCESS;
|
|
#else
|
|
CY_UNUSED_PARAMETER(signal);
|
|
CY_UNUSED_PARAMETER(pin);
|
|
CY_UNUSED_PARAMETER(base);
|
|
CY_UNUSED_PARAMETER(channel_num);
|
|
|
|
return CYHAL_GPIO_RSLT_ERR_NO_OUTPUT_SIGNAL;
|
|
#endif /* defined(CYHAL_PIN_MAP_TCPWM_TR_IN) */
|
|
}
|
|
#endif
|
|
|
|
cy_rslt_t cyhal_quaddec_init(cyhal_quaddec_t *obj, cyhal_gpio_t phi_a, cyhal_gpio_t phi_b,
|
|
cyhal_gpio_t index, cyhal_quaddec_resolution_t resolution,
|
|
const cyhal_clock_t *clk, uint32_t frequency)
|
|
{
|
|
CY_ASSERT(obj != NULL);
|
|
|
|
cy_rslt_t rslt = CY_RSLT_SUCCESS;
|
|
|
|
// Initialize the quadrature object
|
|
// Explicitly marked not allocated resources as invalid to prevent freeing them.
|
|
memset(obj, 0, sizeof(cyhal_quaddec_t));
|
|
obj->phi_a = NC;
|
|
obj->phi_b = NC;
|
|
obj->index = NC;
|
|
obj->tcpwm.resource.type = CYHAL_RSC_INVALID;
|
|
obj->last_counter_value = 1 << (_CYHAL_TCPWM_DATA[obj->tcpwm.resource.block_num].max_count - 1);
|
|
|
|
// Allocate TCPWM resource
|
|
rslt = cyhal_hwmgr_allocate(CYHAL_RSC_TCPWM, &obj->tcpwm.resource);
|
|
|
|
// Basic configuration of TCPWM for quadrature functionality
|
|
if (rslt == CY_RSLT_SUCCESS)
|
|
{
|
|
cy_stc_tcpwm_quaddec_config_t config;
|
|
|
|
obj->tcpwm.base = _CYHAL_TCPWM_DATA[obj->tcpwm.resource.block_num].base;
|
|
_cyhal_tcpwm_init_data(&obj->tcpwm);
|
|
|
|
memset(&config, 0, sizeof(cy_stc_tcpwm_quaddec_config_t));
|
|
|
|
config.resolution = resolution;
|
|
|
|
#if (CY_IP_MXTCPWM_VERSION >= 2U)
|
|
config.phiAInputMode = CY_TCPWM_INPUT_LEVEL; // Pass thorugh (no edge detection)
|
|
config.phiBInputMode = CY_TCPWM_INPUT_LEVEL; // Pass thorugh (no edge detection)
|
|
config.trigger0Event = CY_TCPWM_CNT_TRIGGER_ON_DISABLED; // Disable output trigger0 event generation
|
|
config.trigger1Event = CY_TCPWM_CNT_TRIGGER_ON_DISABLED; // Disable output trigger1 event generation
|
|
#endif
|
|
|
|
// This function is only used to set the resolution and configure the TCPWM for quadrature mode.
|
|
// It also configures the inputs, but that will be overwritten by cyhal_quaddec_connect_digital().
|
|
// So, this must be called before that function is called.
|
|
rslt = Cy_TCPWM_QuadDec_Init(obj->tcpwm.base, _CYHAL_CNT_NUM, &config);
|
|
}
|
|
|
|
// Pin configuration
|
|
if (rslt == CY_RSLT_SUCCESS)
|
|
{
|
|
rslt = cyhal_gpio_init(phi_a, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_NONE, false);
|
|
|
|
if (rslt == CY_RSLT_SUCCESS)
|
|
{
|
|
obj->phi_a = phi_a;
|
|
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
|
|
uint8_t idx = (uint8_t)_cyhal_quaddec_translate_input_signal(CYHAL_QUADDEC_INPUT_PHI_A);
|
|
rslt = cyhal_gpio_enable_output(phi_a, &(obj->tcpwm.inputs[idx]));
|
|
#endif
|
|
}
|
|
|
|
if (rslt == CY_RSLT_SUCCESS)
|
|
{
|
|
rslt = cyhal_gpio_init(phi_b, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_NONE, false);
|
|
}
|
|
|
|
if (rslt == CY_RSLT_SUCCESS)
|
|
{
|
|
obj->phi_b = phi_b;
|
|
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
|
|
uint8_t idx = (uint8_t)_cyhal_quaddec_translate_input_signal(CYHAL_QUADDEC_INPUT_PHI_B);
|
|
rslt = cyhal_gpio_enable_output(phi_b, &(obj->tcpwm.inputs[idx]));
|
|
#endif
|
|
}
|
|
|
|
if (index != NC)
|
|
{
|
|
if (rslt == CY_RSLT_SUCCESS)
|
|
{
|
|
rslt = cyhal_gpio_init(index, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_NONE, false);
|
|
}
|
|
|
|
if (rslt == CY_RSLT_SUCCESS)
|
|
{
|
|
obj->index = index;
|
|
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
|
|
uint8_t idx = (uint8_t)_cyhal_quaddec_translate_input_signal(CYHAL_QUADDEC_INPUT_INDEX);
|
|
rslt = cyhal_gpio_enable_output(index, &(obj->tcpwm.inputs[idx]));
|
|
#endif
|
|
}
|
|
}
|
|
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
|
|
else
|
|
{
|
|
uint8_t idx = (uint8_t)_cyhal_quaddec_translate_input_signal(CYHAL_QUADDEC_INPUT_INDEX);
|
|
obj->tcpwm.inputs[idx] = CYHAL_TRIGGER_CPUSS_ZERO;
|
|
}
|
|
#endif
|
|
|
|
if (rslt != CY_RSLT_SUCCESS)
|
|
{
|
|
rslt = CYHAL_QUADDEC_RSLT_ERR_BAD_ARGUMENT;
|
|
}
|
|
}
|
|
|
|
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
|
|
|
|
// Internal signal configuration
|
|
if (rslt == CY_RSLT_SUCCESS)
|
|
{
|
|
uint8_t idx = (uint8_t)_cyhal_quaddec_translate_input_signal(CYHAL_QUADDEC_INPUT_PHI_A);
|
|
rslt = cyhal_quaddec_connect_digital(obj, obj->tcpwm.inputs[idx], CYHAL_QUADDEC_INPUT_PHI_A);
|
|
if (rslt != CY_RSLT_SUCCESS)
|
|
{
|
|
obj->tcpwm.inputs[idx] = CYHAL_TRIGGER_CPUSS_ZERO;
|
|
}
|
|
}
|
|
|
|
if (rslt == CY_RSLT_SUCCESS)
|
|
{
|
|
uint8_t idx = (uint8_t)_cyhal_quaddec_translate_input_signal(CYHAL_QUADDEC_INPUT_PHI_B);
|
|
rslt = cyhal_quaddec_connect_digital(obj, obj->tcpwm.inputs[idx], CYHAL_QUADDEC_INPUT_PHI_B);
|
|
if (rslt != CY_RSLT_SUCCESS)
|
|
{
|
|
obj->tcpwm.inputs[idx] = CYHAL_TRIGGER_CPUSS_ZERO;
|
|
}
|
|
}
|
|
|
|
if ((rslt == CY_RSLT_SUCCESS) && (index != NC))
|
|
{
|
|
uint8_t idx = (uint8_t)_cyhal_quaddec_translate_input_signal(CYHAL_QUADDEC_INPUT_INDEX);
|
|
rslt = cyhal_quaddec_connect_digital(obj, obj->tcpwm.inputs[idx], CYHAL_QUADDEC_INPUT_INDEX);
|
|
if (rslt != CY_RSLT_SUCCESS)
|
|
{
|
|
obj->tcpwm.inputs[idx] = CYHAL_TRIGGER_CPUSS_ZERO;
|
|
}
|
|
}
|
|
|
|
#elif defined(COMPONENT_CAT2)
|
|
|
|
if (rslt == CY_RSLT_SUCCESS)
|
|
{
|
|
rslt = _cyhal_quaddec_connect_pin(CYHAL_QUADDEC_INPUT_PHI_A, obj->phi_a, obj->tcpwm.base,
|
|
obj->tcpwm.resource.channel_num);
|
|
}
|
|
|
|
if (rslt == CY_RSLT_SUCCESS)
|
|
{
|
|
rslt = _cyhal_quaddec_connect_pin(CYHAL_QUADDEC_INPUT_PHI_B, obj->phi_b, obj->tcpwm.base,
|
|
obj->tcpwm.resource.channel_num);
|
|
}
|
|
|
|
if ((rslt == CY_RSLT_SUCCESS) && (index != NC))
|
|
{
|
|
rslt = _cyhal_quaddec_connect_pin(CYHAL_QUADDEC_INPUT_INDEX, obj->index, obj->tcpwm.base,
|
|
obj->tcpwm.resource.channel_num);
|
|
}
|
|
|
|
#endif
|
|
|
|
// Clock configuration
|
|
if (rslt == CY_RSLT_SUCCESS)
|
|
{
|
|
en_clk_dst_t pclk =
|
|
(en_clk_dst_t)(_CYHAL_TCPWM_DATA[obj->tcpwm.resource.block_num].clock_dst +
|
|
obj->tcpwm.resource.channel_num);
|
|
|
|
if (clk != NULL)
|
|
{
|
|
if (frequency != 0)
|
|
{
|
|
rslt = CYHAL_QUADDEC_RSLT_ERR_BAD_ARGUMENT;
|
|
}
|
|
else
|
|
{
|
|
obj->tcpwm.clock = *clk;
|
|
_cyhal_utils_update_clock_format(&obj->tcpwm.clock);
|
|
|
|
if (Cy_SysClk_PeriphAssignDivider(pclk, (cy_en_divider_types_t)obj->tcpwm.clock.block,
|
|
obj->tcpwm.clock.channel) != CY_SYSCLK_SUCCESS)
|
|
{
|
|
rslt = CYHAL_QUADDEC_RSLT_ERR_CLOCK_INIT;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rslt = _cyhal_quaddec_configure_clock(&obj->tcpwm, pclk, frequency);
|
|
}
|
|
|
|
if (rslt == CY_RSLT_SUCCESS)
|
|
{
|
|
obj->tcpwm.clock_hz = cyhal_clock_get_frequency(&obj->tcpwm.clock);
|
|
}
|
|
}
|
|
|
|
// Enable the quadrature function
|
|
if (rslt == CY_RSLT_SUCCESS)
|
|
{
|
|
Cy_TCPWM_QuadDec_Enable(obj->tcpwm.base, _CYHAL_CNT_NUM);
|
|
}
|
|
else
|
|
{
|
|
cyhal_quaddec_free(obj);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
void cyhal_quaddec_free(cyhal_quaddec_t *obj)
|
|
{
|
|
CY_ASSERT(obj != NULL);
|
|
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
|
|
uint8_t idx_phi_a = (uint8_t)_cyhal_quaddec_translate_input_signal(CYHAL_QUADDEC_INPUT_PHI_A);
|
|
if ((obj->phi_a != NC) && (obj->tcpwm.inputs[idx_phi_a] != CYHAL_TRIGGER_CPUSS_ZERO))
|
|
{
|
|
cyhal_quaddec_disconnect_digital(obj, obj->tcpwm.inputs[idx_phi_a], CYHAL_QUADDEC_INPUT_PHI_A);
|
|
}
|
|
uint8_t idx_phi_b = (uint8_t)_cyhal_quaddec_translate_input_signal(CYHAL_QUADDEC_INPUT_PHI_B);
|
|
if ((obj->phi_b != NC) && (obj->tcpwm.inputs[idx_phi_b] != CYHAL_TRIGGER_CPUSS_ZERO))
|
|
{
|
|
cyhal_quaddec_disconnect_digital(obj, obj->tcpwm.inputs[idx_phi_b], CYHAL_QUADDEC_INPUT_PHI_B);
|
|
}
|
|
uint8_t idx_index = (uint8_t)_cyhal_quaddec_translate_input_signal(CYHAL_QUADDEC_INPUT_INDEX);
|
|
if ((obj->index != NC) && (obj->tcpwm.inputs[idx_index] != CYHAL_TRIGGER_CPUSS_ZERO))
|
|
{
|
|
cyhal_quaddec_disconnect_digital(obj, obj->tcpwm.inputs[idx_index], CYHAL_QUADDEC_INPUT_INDEX);
|
|
}
|
|
#endif
|
|
_cyhal_utils_release_if_used(&obj->phi_a);
|
|
_cyhal_utils_release_if_used(&obj->phi_b);
|
|
_cyhal_utils_release_if_used(&obj->index);
|
|
_cyhal_tcpwm_free(&obj->tcpwm);
|
|
}
|
|
|
|
cy_rslt_t cyhal_quaddec_start(cyhal_quaddec_t *obj)
|
|
{
|
|
CY_ASSERT(obj != NULL);
|
|
if (_cyhal_tcpwm_pm_transition_pending())
|
|
{
|
|
return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
|
|
}
|
|
Cy_TCPWM_QuadDec_Enable(obj->tcpwm.base, _CYHAL_CNT_NUM);
|
|
|
|
// Trigger reload/index the QuadDec.
|
|
// From the TRM, "A reload trigger must be provided through firmware to start the counter if
|
|
// the hardware reload signal is not enabled."
|
|
#if defined(CY_IP_MXTCPWM) && (CY_IP_MXTCPWM_VERSION >= 2)
|
|
Cy_TCPWM_TriggerReloadOrIndex_Single(obj->tcpwm.base, _CYHAL_CNT_NUM);
|
|
#else
|
|
Cy_TCPWM_TriggerReloadOrIndex(obj->tcpwm.base, 1 << _CYHAL_CNT_NUM);
|
|
#endif
|
|
|
|
obj->last_counter_value = 1 << (_CYHAL_TCPWM_DATA[obj->tcpwm.resource.block_num].max_count - 1);
|
|
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
|
|
cy_rslt_t cyhal_quaddec_stop(cyhal_quaddec_t *obj)
|
|
{
|
|
CY_ASSERT(obj != NULL);
|
|
Cy_TCPWM_QuadDec_Disable(obj->tcpwm.base, _CYHAL_CNT_NUM);
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
|
|
int32_t cyhal_quaddec_get_delta(cyhal_quaddec_t *obj)
|
|
{
|
|
CY_ASSERT(obj != NULL);
|
|
|
|
uint32_t midpoint = 1 << (_CYHAL_TCPWM_DATA[obj->tcpwm.resource.block_num].max_count - 1);
|
|
uint32_t max_delta = midpoint >> 1;
|
|
uint32_t max_counter_value = (midpoint == 0x8000) ? 0xFFFF : 0xFFFFFFFF;
|
|
uint32_t current_counter_value = Cy_TCPWM_QuadDec_GetCounter(obj->tcpwm.base, _CYHAL_CNT_NUM);
|
|
int32_t delta = current_counter_value - obj->last_counter_value;
|
|
|
|
// Overflow has occurred
|
|
if (delta < (int32_t)(-max_delta))
|
|
{
|
|
delta = max_counter_value - obj->last_counter_value;
|
|
delta += current_counter_value - midpoint;
|
|
}
|
|
// Underflow has occurred
|
|
else if (delta > (int32_t)max_delta)
|
|
{
|
|
delta = (int32_t)(-obj->last_counter_value);
|
|
delta += current_counter_value - midpoint;
|
|
}
|
|
|
|
obj->last_counter_value = current_counter_value;
|
|
|
|
return delta;
|
|
}
|
|
|
|
uint32_t cyhal_quaddec_read_counter(const cyhal_quaddec_t *obj)
|
|
{
|
|
CY_ASSERT(obj != NULL);
|
|
return Cy_TCPWM_QuadDec_GetCounter(obj->tcpwm.base, _CYHAL_CNT_NUM);
|
|
}
|
|
|
|
uint32_t cyhal_quaddec_read_capture(const cyhal_quaddec_t *obj)
|
|
{
|
|
CY_ASSERT(obj != NULL);
|
|
#if defined(CY_IP_MXTCPWM) && (CY_IP_MXTCPWM_VERSION >= 2)
|
|
return Cy_TCPWM_QuadDec_GetCapture0Val(obj->tcpwm.base, _CYHAL_CNT_NUM);
|
|
#else
|
|
return Cy_TCPWM_QuadDec_GetCapture(obj->tcpwm.base, _CYHAL_CNT_NUM);
|
|
#endif
|
|
}
|
|
|
|
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
|
|
|
|
static cyhal_tcpwm_input_t _cyhal_quaddec_translate_input_signal(cyhal_quaddec_input_t signal)
|
|
{
|
|
switch (signal)
|
|
{
|
|
case CYHAL_QUADDEC_INPUT_PHI_A:
|
|
return CYHAL_TCPWM_INPUT_COUNT;
|
|
case CYHAL_QUADDEC_INPUT_PHI_B:
|
|
return CYHAL_TCPWM_INPUT_START;
|
|
case CYHAL_QUADDEC_INPUT_STOP:
|
|
return CYHAL_TCPWM_INPUT_STOP;
|
|
case CYHAL_QUADDEC_INPUT_INDEX:
|
|
return CYHAL_TCPWM_INPUT_RELOAD;
|
|
}
|
|
CY_ASSERT(false);
|
|
return (cyhal_tcpwm_input_t)0;
|
|
}
|
|
|
|
cy_rslt_t cyhal_quaddec_connect_digital(cyhal_quaddec_t *obj, cyhal_source_t source, cyhal_quaddec_input_t signal)
|
|
{
|
|
cyhal_tcpwm_input_t tcpwm_signal;
|
|
cyhal_edge_type_t input_type;
|
|
|
|
switch (signal)
|
|
{
|
|
case CYHAL_QUADDEC_INPUT_PHI_A:
|
|
case CYHAL_QUADDEC_INPUT_PHI_B:
|
|
input_type = CYHAL_EDGE_TYPE_LEVEL;
|
|
break;
|
|
case CYHAL_QUADDEC_INPUT_STOP:
|
|
case CYHAL_QUADDEC_INPUT_INDEX:
|
|
input_type = CYHAL_EDGE_TYPE_RISING_EDGE;
|
|
break;
|
|
default:
|
|
return CYHAL_QUADDEC_RSLT_ERR_BAD_ARGUMENT;
|
|
}
|
|
|
|
tcpwm_signal = _cyhal_quaddec_translate_input_signal(signal);
|
|
|
|
return _cyhal_tcpwm_connect_digital(&(obj->tcpwm), source, tcpwm_signal, input_type);
|
|
}
|
|
|
|
cy_rslt_t cyhal_quaddec_disconnect_digital(cyhal_quaddec_t *obj, cyhal_source_t source, cyhal_quaddec_input_t signal)
|
|
{
|
|
return _cyhal_tcpwm_disconnect_digital(&(obj->tcpwm), source,
|
|
_cyhal_quaddec_translate_input_signal(signal));
|
|
}
|
|
|
|
#elif defined(COMPONENT_CAT2)
|
|
|
|
cy_rslt_t cyhal_quaddec_connect_digital(cyhal_quaddec_t *obj, cyhal_source_t source, cyhal_quaddec_input_t signal)
|
|
{
|
|
CY_UNUSED_PARAMETER(obj);
|
|
CY_UNUSED_PARAMETER(source);
|
|
CY_UNUSED_PARAMETER(signal);
|
|
return CYHAL_QUADDEC_RSLT_ERR_NOT_SUPPORTED;
|
|
}
|
|
|
|
cy_rslt_t cyhal_quaddec_disconnect_digital(cyhal_quaddec_t *obj, cyhal_source_t source, cyhal_quaddec_input_t signal)
|
|
{
|
|
CY_UNUSED_PARAMETER(obj);
|
|
CY_UNUSED_PARAMETER(source);
|
|
CY_UNUSED_PARAMETER(signal);
|
|
return CYHAL_QUADDEC_RSLT_ERR_NOT_SUPPORTED;
|
|
}
|
|
|
|
#endif
|
|
|
|
static cyhal_tcpwm_output_t _cyhal_quaddec_translate_output_signal(cyhal_quaddec_output_t signal)
|
|
{
|
|
switch (signal)
|
|
{
|
|
case CYHAL_QUADDEC_OUTPUT_COMPARE_MATCH:
|
|
return CYHAL_TCPWM_OUTPUT_COMPARE_MATCH;
|
|
}
|
|
CY_ASSERT(false);
|
|
return (cyhal_tcpwm_output_t)0;
|
|
}
|
|
|
|
cy_rslt_t cyhal_quaddec_enable_output(cyhal_quaddec_t *obj, cyhal_quaddec_output_t signal, cyhal_source_t *source)
|
|
{
|
|
if (signal != CYHAL_QUADDEC_OUTPUT_COMPARE_MATCH)
|
|
{
|
|
return CYHAL_QUADDEC_RSLT_ERR_BAD_ARGUMENT;
|
|
}
|
|
|
|
return _cyhal_tcpwm_enable_output(&(obj->tcpwm), _cyhal_quaddec_translate_output_signal(signal), source);
|
|
}
|
|
|
|
cy_rslt_t cyhal_quaddec_disable_output(cyhal_quaddec_t *obj, cyhal_quaddec_output_t signal)
|
|
{
|
|
if (signal != CYHAL_QUADDEC_OUTPUT_COMPARE_MATCH)
|
|
return CYHAL_QUADDEC_RSLT_ERR_BAD_ARGUMENT;
|
|
|
|
return _cyhal_tcpwm_disable_output(&(obj->tcpwm), _cyhal_quaddec_translate_output_signal(signal));
|
|
}
|