1 /***************************************************************************//**
2 * \file cyhal_tcpwm_common.h
3 *
4 * \brief
5 * Code shared between the Infineon Timer/Counter and PWM.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2019-2021 Cypress Semiconductor Corporation (an Infineon company) or
10 * an affiliate of Cypress Semiconductor Corporation
11 *
12 * SPDX-License-Identifier: Apache-2.0
13 *
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
17 *
18 *     http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
25 *******************************************************************************/
26 
27 /** \cond INTERNAL */
28 /**
29  * \addtogroup group_hal_impl_tcpwm_common TCPWM Common Functionality
30  * \ingroup group_hal_impl
31  * \{
32  * Code shared between the Infineon Timer / Counter and PWM.
33  */
34 
35 #pragma once
36 
37 #include <stdint.h>
38 #include <stdbool.h>
39 #include "cyhal_hw_types.h"
40 #include "cyhal_interconnect.h"
41 
42 #if defined(__cplusplus)
43 extern "C" {
44 #endif /* __cplusplus */
45 
46 // Value comes from IP limitation
47 #define _CYHAL_TCPWM_MAX_GRPS_PER_IP_BLOCK  (4u)
48 
49 #if defined(CY_IP_MXTCPWM_INSTANCES) || defined(CY_IP_M0S8TCPWM_INSTANCES)
50 
51 #if defined(CY_IP_MXTCPWM_INSTANCES)
52     #if (CY_IP_MXTCPWM_VERSION == 1)
53         // Total number of TCPWM groups
54         #define _CYHAL_TCPWM_INSTANCES     CY_IP_MXTCPWM_INSTANCES
55         // Counter number relative to the start of the IP block
56         #define _CYHAL_TCPWM_CNT_NUMBER(resource) ((resource).channel_num)
57         // Cobvert driver 'block' to IP block
58         #define _CYHAL_TCPWM_GET_IP_BLOCK(block) (block)
59     #else // (CY_IP_MXTCPWM_VERSION >= 2)
60         #define _CYHAL_TCPWM_GET_IP_BLOCK(block) ((block) / _CYHAL_TCPWM_MAX_GRPS_PER_IP_BLOCK)
61         // Used to grab the group index relative to its IP block
62         #define _CYHAL_TCPWM_GET_GRP(block) ((block) % _CYHAL_TCPWM_MAX_GRPS_PER_IP_BLOCK)
63         #if (CY_IP_MXTCPWM_INSTANCES == 1)
64             #define _CYHAL_TCPWM_INSTANCES     TCPWM_GRP_NR
65             #define _CYHAL_TCPWM_CNT_NUMBER(resource) (((resource).block_num << 8) | (resource).channel_num)
66         #elif (CY_IP_MXTCPWM_INSTANCES == 2)
67             #define _CYHAL_TCPWM_INSTANCES     (TCPWM0_GRP_NR + TCPWM1_GRP_NR)
68             // This is based on the model of 4x continuous groups mapping to x IP blocks (0-3 to 1, 4-7 to 2, etc)
69             #define _CYHAL_TCPWM_CNT_NUMBER(resource) ((((resource).block_num % _CYHAL_TCPWM_MAX_GRPS_PER_IP_BLOCK) << 8) | (resource).channel_num)
70         #else
71             #warning Unhandled TCPWM instance count
72         #endif
73     #endif
74 #elif defined(CY_IP_M0S8TCPWM_INSTANCES)
75     #define _CYHAL_TCPWM_CNT_NUMBER(resource) ((resource).channel_num)
76     #define _CYHAL_TCPWM_INSTANCES     CY_IP_M0S8TCPWM_INSTANCES
77     #define _CYHAL_TCPWM_GET_IP_BLOCK(block) (block)
78 #endif
79 
80 // Used to adjust block value for indexing _CYHAL_TCPWM_DATA[] and other arrays which do not include indexes for empty blocks
81 #if (CY_IP_MXTCPWM_VERSION == 2)
82     #if (CY_IP_MXTCPWM_INSTANCES == 1)
83         #define _CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block) (block)
84     #elif (CY_IP_MXTCPWM_INSTANCES == 2)
85         #define _CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block)    ((_CYHAL_TCPWM_GET_IP_BLOCK(block) == 0) ? (block) : (_CYHAL_TCPWM_GET_GRP(block) + TCPWM0_GRP_NR))
86     #else
87         #warning Unhandled TCPWM instance count
88     #endif
89 #else
90     #define _CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block) (block)
91 #endif
92 
93 #if defined(CY_IP_MXTCPWM_INSTANCES)
94 #if (CY_IP_MXTCPWM_VERSION == 1)
95     #if (CY_IP_MXTCPWM_INSTANCES == 0)
96         #define _CYHAL_TCPWM_CHANNELS (0u)
97     #elif (CY_IP_MXTCPWM_INSTANCES == 1)
98         #define _CYHAL_TCPWM_CHANNELS (TCPWM0_CNT_NR)
99     #elif (CY_IP_MXTCPWM_INSTANCES == 2)
100         #define _CYHAL_TCPWM_CHANNELS (TCPWM0_CNT_NR + TCPWM1_CNT_NR)
101     #else
102         #warning Unhandled TCPWM instance count
103     #endif
104 #else // (CY_IP_MXTCPWM_VERSION >= 2)
105     #if (CY_IP_MXTCPWM_INSTANCES == 1)
106         #if (TCPWM_GRP_NR == 0)
107             #define _CYHAL_TCPWM_CHANNELS (0U)
108         #elif (TCPWM_GRP_NR == 1)
109             #define _CYHAL_TCPWM_CHANNELS (TCPWM_GRP_NR0_GRP_GRP_CNT_NR)
110         #elif (TCPWM_GRP_NR == 2)
111             #define _CYHAL_TCPWM_CHANNELS (TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR)
112         #elif (TCPWM_GRP_NR == 3)
113             #define _CYHAL_TCPWM_CHANNELS (TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR + TCPWM_GRP_NR2_GRP_GRP_CNT_NR)
114         #elif (TCPWM_GRP_NR == 4)
115             #define _CYHAL_TCPWM_CHANNELS (TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR + TCPWM_GRP_NR2_GRP_GRP_CNT_NR + TCPWM_GRP_NR3_GRP_GRP_CNT_NR)
116         #endif
117     #elif (CY_IP_MXTCPWM_INSTANCES == 2)
118         #if (TCPWM0_GRP_NR == 0)
119             #define _CYHAL_TCPWM0_CHANNELS (0U)
120         #elif (TCPWM0_GRP_NR == 1)
121             #define _CYHAL_TCPWM0_CHANNELS (TCPWM0_GRP_NR0_GRP_GRP_CNT_NR)
122         #elif (TCPWM0_GRP_NR == 2)
123             #define _CYHAL_TCPWM0_CHANNELS (TCPWM0_GRP_NR0_GRP_GRP_CNT_NR + TCPWM0_GRP_NR1_GRP_GRP_CNT_NR)
124         #elif (TCPWM0_GRP_NR == 3)
125             #define _CYHAL_TCPWM0_CHANNELS (TCPWM0_GRP_NR0_GRP_GRP_CNT_NR + TCPWM0_GRP_NR1_GRP_GRP_CNT_NR + TCPWM0_GRP_NR2_GRP_GRP_CNT_NR)
126         #elif (TCPWM0_GRP_NR == 4)
127             #define _CYHAL_TCPWM0_CHANNELS (TCPWM0_GRP_NR0_GRP_GRP_CNT_NR + TCPWM0_GRP_NR1_GRP_GRP_CNT_NR + TCPWM0_GRP_NR2_GRP_GRP_CNT_NR + TCPWM0_GRP_NR3_GRP_GRP_CNT_NR)
128         #endif
129         #ifndef _CYHAL_TCPWM0_CHANNELS
130             #error "Unhandled TCPWM0_GRP_NR count"
131         #endif
132         #if (TCPWM1_GRP_NR == 0)
133             #define _CYHAL_TCPWM1_CHANNELS (0U)
134         #elif (TCPWM1_GRP_NR == 1)
135             #define _CYHAL_TCPWM1_CHANNELS (TCPWM1_GRP_NR0_GRP_GRP_CNT_NR)
136         #elif (TCPWM1_GRP_NR == 2)
137             #define _CYHAL_TCPWM1_CHANNELS (TCPWM1_GRP_NR0_GRP_GRP_CNT_NR + TCPWM1_GRP_NR1_GRP_GRP_CNT_NR)
138         #elif (TCPWM1_GRP_NR == 3)
139             #define _CYHAL_TCPWM1_CHANNELS (TCPWM1_GRP_NR0_GRP_GRP_CNT_NR + TCPWM1_GRP_NR1_GRP_GRP_CNT_NR + TCPWM1_GRP_NR2_GRP_GRP_CNT_NR)
140         #elif (TCPWM1_GRP_NR == 4)
141             #define _CYHAL_TCPWM1_CHANNELS (TCPWM1_GRP_NR0_GRP_GRP_CNT_NR + TCPWM1_GRP_NR1_GRP_GRP_CNT_NR + TCPWM1_GRP_NR2_GRP_GRP_CNT_NR + TCPWM1_GRP_NR3_GRP_GRP_CNT_NR)
142         #endif
143         #ifndef _CYHAL_TCPWM1_CHANNELS
144             #error "Unhandled TCPWM1_GRP_NR count"
145         #endif
146 
147         #define _CYHAL_TCPWM_CHANNELS (_CYHAL_TCPWM0_CHANNELS + _CYHAL_TCPWM1_CHANNELS)
148     #else
149         #warning Unhandled TCPWM instance count
150     #endif
151 #endif
152 #elif defined(CY_IP_M0S8TCPWM_INSTANCES)
153     #if (CY_IP_M0S8TCPWM_INSTANCES == 1)
154         #define _CYHAL_TCPWM_CHANNELS (TCPWM_CNT_NR)
155     #else
156         #warning Unhandled TCPWM instance count
157     #endif
158 #endif
159 
160 #if (CY_IP_MXTCPWM_VERSION == 1U)
161     extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1];
162     extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1];
163 #elif (CY_IP_MXTCPWM_VERSION == 2U)
164     // PSoC™ 6 devices with trigmux vers2 also have a number of reserved input
165     // lines defined by TCPWM_TR_ONE_CNT_NR.
166     #if (CY_IP_MXTCPWM_INSTANCES == 1)
167     extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1];
168     extern const uint16_t  _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1];
169     #elif (CY_IP_MXTCPWM_INSTANCES == 2)
170     extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[2];
171     extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[2];
172     #else
173     #warning Unhandled TCPWM instance count
174     #endif
175 #else // (CY_IP_M0S8TCPWM_VERSION == 2)
176     // PSoC™ 4 devices have a number of reserved input lines coming directly from
177     // GPIO triggers (depending on exact architecture).
178     #if defined(CY_DEVICE_PSOC4AS1)
179         // 12 GPIO trigger lines reserved (but some may be unused, depending on
180         // pin package)
181         extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1];
182         extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1];
183     #else
184         // 7 GPIO trigger lines reserved (but some may be unused, depending on
185         // pin package)
186         extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1];
187         extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1];
188     #endif
189 #endif
190 
191 /** \addtogroup group_hal_results_tcpwm TCPWM HAL Results
192  *  TCPWM specific return codes
193  *  \ingroup group_hal_results
194  *  \{ *//**
195  */
196 
197 /** Bad argument. eg: null pointer */
198 #define CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT                   \
199     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_IMPL_TCPWM, 0))
200 /** Failed to find free input signal */
201 #define CYHAL_TCPWM_RSLT_ERR_NO_FREE_INPUT_SIGNALS          \
202     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_IMPL_TCPWM, 1))
203 /** Failed to find free output signal */
204 #define CYHAL_TCPWM_RSLT_ERR_NO_FREE_OUTPUT_SIGNALS         \
205     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_IMPL_TCPWM, 2))
206 
207 /**
208  * \}
209  */
210 
211 /** TCPWM/counter input signal */
212 typedef enum
213 {
214     CYHAL_TCPWM_INPUT_START,    //!< Start signal
215     CYHAL_TCPWM_INPUT_STOP,     //!< Stop signal
216     CYHAL_TCPWM_INPUT_RELOAD,   //!< Reload signal
217     CYHAL_TCPWM_INPUT_COUNT,    //!< Count signal
218     CYHAL_TCPWM_INPUT_CAPTURE,  //!< Capture signal
219 } cyhal_tcpwm_input_t;
220 
221 /** The number of unique TCPWM inputs as defined by cyhal_tcpwm_input_t */
222 #define _CYHAL_TCPWM_INPUTS     5
223 
224 /** TCPWM/counter output signal */
225 typedef enum
226 {
227     CYHAL_TCPWM_OUTPUT_OVERFLOW,       //!< Overflow signal
228     CYHAL_TCPWM_OUTPUT_UNDERFLOW,      //!< Underflow signal
229     CYHAL_TCPWM_OUTPUT_COMPARE_MATCH,  //!< Compare match signal
230     CYHAL_TCPWM_OUTPUT_TERMINAL_COUNT, //!< Terminal count signal (logical OR of overflow and underflow signal)
231     CYHAL_TCPWM_OUTPUT_LINE_OUT,       //!< Line out signal
232 } cyhal_tcpwm_output_t;
233 
234 /** The number of unique TCPWM outputs as defined by cyhal_tcpwm_output_t */
235 #define _CYHAL_TCPWM_OUTPUTS     5
236 
237 /** Handler for TCPWM interrupts */
238 typedef void(*_cyhal_tcpwm_event_callback_t)(void *callback_arg, int event);
239 
240 /** Holds data about a single TCPWM */
241 typedef struct {
242     TCPWM_Type*  base; //!< TCPWM base
243     en_clk_dst_t clock_dst; //!< TCPWM clock connections base
244     uint32_t     max_count; //!< TCPWM counter width
245     uint8_t      num_channels; //!< Number of channels on the TCPWM
246     uint8_t      channel_offset; //!< Offset from channels on previous TCPWM
247 #if !defined(COMPONENT_CAT1C)
248     uint8_t      isr_offset; //!< TCPWM base IRQn (channel 0 IRQn)
249 #else
250     /** CAT1C device has number of interrupts, which exceeds uint8_t type max. value */
251     uint16_t     isr_offset; //!< TCPWM base IRQn (channel 0 IRQn)
252 #endif // not CAT1C or CAT1C
253 } _cyhal_tcpwm_data_t;
254 
255 /** Contains data about all of the TCPWMs */
256 extern const _cyhal_tcpwm_data_t _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_INSTANCES];
257 
258 #ifdef CY_DEVICE_PSOC6A256K
259 /** Contains bitfield of in use data for all TCPWM output trigger lines. There
260  * are 2 available output lines per counter */
261 extern uint8_t _CYHAL_OUTPUT_TRIGGERS_USED[TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR];
262 #endif
263 
264 /**
265  * Free a timer/counter or a PWM object's shared data
266  *
267  * @param[in] obj The timer/counter or the PWM resource
268  */
269 void _cyhal_tcpwm_free(cyhal_tcpwm_t *obj);
270 
271 /** Initialize a timer/counter or PWM object's callback data.
272  *
273  * @param[in,out] tcpwm    The shared data struct between timer/counter and PWM
274  */
275 void _cyhal_tcpwm_init_data(cyhal_tcpwm_t *tcpwm);
276 
277 /** The TCPWM interrupt handler registration
278  *
279  * @param[in] resource      The timer/counter or PWM resource
280  * @param[in] callback      The callback handler which will be invoked when the event occurs
281  * @param[in] callback_arg  Generic argument that will be provided to the callback when called
282  */
283 void _cyhal_tcpwm_register_callback(cyhal_resource_inst_t *resource, cy_israddress callback, void *callback_arg);
284 
285 /** Configure TCPWM event enablement.
286  *
287  * @param[in] tcpwm          The shared data struct between timer/counter and PWM
288  * @param[in] resource      The timer/counter or PWM resource
289  * @param[in] event         The timer/counter or PWM event type
290  * @param[in] intr_priority The priority for NVIC interrupt events
291  * @param[in] enable        True to turn on events, False to turn off
292  */
293 void _cyhal_tcpwm_enable_event(cyhal_tcpwm_t *tcpwm, cyhal_resource_inst_t *resource, uint32_t event, uint8_t intr_priority, bool enable);
294 
295 /** Returns whether power management transition should be allowed.
296  *
297  * @return true if no tcpwm is actively blocking power mode transition
298  */
299 bool _cyhal_tcpwm_pm_transition_pending(void);
300 
301 /** Connects a source signal and configures and enables a TCPWM event to be
302  * triggered from that signal. These TCPWM events can be configured
303  * independently and connect to the same or different source signals.
304  *
305  * @param[in] obj      TCPWM HAL object
306  * @param[in] source   Source signal obtained from another driver's cyhal_<PERIPH>_enable_output
307  * @param[in] signal   The TCPWM input signal
308  * @param[in] type     The edge type of the signal to connect
309  * @return The status of the connection
310  * */
311 cy_rslt_t _cyhal_tcpwm_connect_digital(cyhal_tcpwm_t *obj, cyhal_source_t source, cyhal_tcpwm_input_t signal, cyhal_edge_type_t type);
312 
313 /** Enables the specified output signal from a TCPWM that will be triggered
314  * when the corresponding event occurs. Multiple output signals can be
315  * configured simultaneously.
316  *
317  * @param[in]  obj      TCPWM HAL object
318  * @param[in]  signal   The TCPWM output signal
319  * @param[out] source   Pointer to user-allocated source signal object which
320  * will be initialized by enable_output. source should be passed to
321  * (dis)connect_digital functions to (dis)connect the associated endpoints.
322  * @return The status of the output enable
323  * */
324 cy_rslt_t _cyhal_tcpwm_enable_output(cyhal_tcpwm_t *obj, cyhal_tcpwm_output_t signal, cyhal_source_t *source);
325 
326 /** Disconnects a source signal and disables the corresponding input to a TCPWM
327  *
328  * @param[in] obj      TCPWM HAL object
329  * @param[in] source   Source signal from cyhal_<PERIPH>_enable_output to disable
330  * @param[in] signal   The TCPWM input signal
331  * @return The status of the disconnection
332  * */
333 cy_rslt_t _cyhal_tcpwm_disconnect_digital(cyhal_tcpwm_t *obj, cyhal_source_t source, cyhal_tcpwm_input_t signal);
334 
335 /** Disables the specified output signal from a TCPWM.
336  *
337  * @param[in]  obj      TCPWM HAL object
338  * @param[in]  resource TCPWM resource
339  * @param[in]  signal   The TCPWM output signal
340  * @return The status of the output disable
341  * */
342 cy_rslt_t _cyhal_tcpwm_disable_output(cyhal_tcpwm_t *obj, cyhal_tcpwm_output_t signal);
343 
344 #if (defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)) && \
345     ((CY_IP_MXTCPWM_VERSION == 1) || (CY_IP_MXTCPWM_VERSION == 2) || (CY_IP_M0S8TCPWM_VERSION == 2))
346 /** Get the destination reference for the provided TCPWM block and trigger
347  *
348  * @param[in]  block        TCPWM block number
349  * @param[in]  trig_index   The trigger index to get the destination for
350  * @return A destination that a signal can be connected to for the specified TCPWM block
351  * */
352 cyhal_dest_t _cyhal_tpwm_calculate_dest(uint8_t block, uint8_t trig_index);
353 #endif
354 
355 #if defined(__cplusplus)
356 }
357 #endif /* __cplusplus */
358 
359 #endif /* defined(CY_IP_MXTCPWM_INSTANCES) || defined(CY_IP_M0S8TCPWM_INSTANCES) */
360 
361 /** \} group_hal_impl_tcpwm_common */
362 /** \endcond */
363