1 /***************************************************************************//**
2 * \file cyhal_timer.c
3 *
4 * \brief
5 * Provides a high level interface for interacting with the Infineon Timer/Counter.
6 * This interface abstracts out the chip specific details. If any chip specific
7 * functionality is necessary, or performance is critical the low level functions
8 * can be used directly.
9 *
10 ********************************************************************************
11 * \copyright
12 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
13 * an affiliate of Cypress Semiconductor Corporation
14 *
15 * SPDX-License-Identifier: Apache-2.0
16 *
17 * Licensed under the Apache License, Version 2.0 (the "License");
18 * you may not use this file except in compliance with the License.
19 * You may obtain a copy of the License at
20 *
21 *     http://www.apache.org/licenses/LICENSE-2.0
22 *
23 * Unless required by applicable law or agreed to in writing, software
24 * distributed under the License is distributed on an "AS IS" BASIS,
25 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26 * See the License for the specific language governing permissions and
27 * limitations under the License.
28 *******************************************************************************/
29 #include <string.h>
30 #if !defined(COMPONENT_CAT5)
31 #include "cy_device_headers.h"
32 #endif
33 #include "cyhal_timer_impl.h"
34 #include "cyhal_hwmgr.h"
35 #include "cyhal_gpio.h"
36 #include "cyhal_interconnect.h"
37 #include "cyhal_syspm.h"
38 #include "cyhal_clock.h"
39 #if defined(COMPONENT_CAT5)
40 #include "cyhal_irq_impl.h"
41 #endif
42 
43 #if (CYHAL_DRIVER_AVAILABLE_TIMER)
44 
45 #if defined(__cplusplus)
46 extern "C" {
47 #endif
48 
49 static const cy_stc_tcpwm_counter_config_t _cyhal_timer_default_config =
50 {
51     .period = 32768,
52     .clockPrescaler = CY_TCPWM_COUNTER_PRESCALER_DIVBY_1,
53     .runMode = CY_TCPWM_COUNTER_CONTINUOUS,
54     .countDirection = CY_TCPWM_COUNTER_COUNT_UP,
55     .compareOrCapture = CY_TCPWM_COUNTER_MODE_CAPTURE,
56     .compare0 = 16384,
57     .compare1 = 16384,
58     .enableCompareSwap = false,
59     .interruptSources = CY_TCPWM_INT_NONE,
60     .captureInputMode = 0x3U,
61     .captureInput = CY_TCPWM_INPUT_0,
62     .reloadInputMode = 0x3U,
63     .reloadInput = CY_TCPWM_INPUT_0,
64     .startInputMode = 0x3U,
65     .startInput = CY_TCPWM_INPUT_0,
66     .stopInputMode = 0x3U,
67     .stopInput = CY_TCPWM_INPUT_0,
68     .countInputMode = 0x3U,
69     .countInput = CY_TCPWM_INPUT_1,
70 #if (CY_IP_MXTCPWM_VERSION >= 2U)
71     .capture1InputMode = 0x3U,
72     .capture1Input = CY_TCPWM_INPUT_0,
73     .enableCompare1Swap = false,
74     .compare2 = 16384,
75     .compare3 = 16384,
76     .trigger0Event = CY_TCPWM_CNT_TRIGGER_ON_DISABLED,
77     .trigger1Event = CY_TCPWM_CNT_TRIGGER_ON_DISABLED,
78 #endif
79 };
80 
81 /** Convert timer direction from the HAL enum to the corresponding PDL constant
82   *
83   * @param[in] direction The direction, as a HAL enum value
84   * @return The direction, as a PDL constant
85   */
_cyhal_timer_convert_direction(cyhal_timer_direction_t direction)86 static inline uint32_t _cyhal_timer_convert_direction(cyhal_timer_direction_t direction)
87 {
88     switch (direction)
89     {
90         case CYHAL_TIMER_DIR_UP:
91             return CY_TCPWM_COUNTER_COUNT_UP;
92         case CYHAL_TIMER_DIR_DOWN:
93             return CY_TCPWM_COUNTER_COUNT_DOWN;
94         case CYHAL_TIMER_DIR_UP_DOWN:
95             return CY_TCPWM_COUNTER_COUNT_UP_DOWN_2;
96         default:
97             CY_ASSERT(false);
98             return CY_TCPWM_COUNTER_COUNT_UP;
99     }
100 }
101 
102 /*******************************************************************************
103 *       Timer HAL Functions
104 *******************************************************************************/
105 
_cyhal_timer_init_hw(cyhal_timer_t * obj,const cy_stc_tcpwm_counter_config_t * config,const cyhal_clock_t * clk)106 cy_rslt_t _cyhal_timer_init_hw(cyhal_timer_t *obj, const cy_stc_tcpwm_counter_config_t *config, const cyhal_clock_t *clk)
107 {
108     cy_rslt_t result = CY_RSLT_SUCCESS;
109 
110     cyhal_resource_inst_t *timer = &obj->tcpwm.resource;
111     obj->tcpwm.base = _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(timer->block_num)].base;
112 
113     en_clk_dst_t pclk = (en_clk_dst_t)(_CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(timer->block_num)].clock_dst + timer->channel_num);
114 
115     if (NULL != clk)
116     {
117         obj->tcpwm.clock = *clk;
118         obj->tcpwm.clock_hz = cyhal_clock_get_frequency(&obj->tcpwm.clock);
119         if (CY_SYSCLK_SUCCESS != _cyhal_utils_peri_pclk_assign_divider(pclk, &(obj->tcpwm.clock)))
120         {
121             result = CYHAL_TIMER_RSLT_ERR_CLOCK_INIT;
122         }
123     }
124     else if (CY_RSLT_SUCCESS == (result = _cyhal_utils_allocate_clock(&(obj->tcpwm.clock), timer, CYHAL_CLOCK_BLOCK_PERIPHERAL_16BIT, true)))
125     {
126         obj->tcpwm.dedicated_clock = true;
127         #if defined(COMPONENT_CAT5)
128         // CAT5 lacks hardware required to divide from 96MHz to 1MHz
129         result = cyhal_timer_set_frequency(obj, CYHAL_TIMER_DEFAULT_FREQ * 3);
130         #else
131         result = cyhal_timer_set_frequency(obj, CYHAL_TIMER_DEFAULT_FREQ);
132         #endif
133         if (CY_RSLT_SUCCESS == result)
134         {
135             if (CY_SYSCLK_SUCCESS != _cyhal_utils_peri_pclk_assign_divider(pclk, &(obj->tcpwm.clock)))
136             {
137                 result = CYHAL_TIMER_RSLT_ERR_CLOCK_INIT;
138             }
139         }
140     }
141 
142     if (CY_RSLT_SUCCESS == result)
143     {
144         result = Cy_TCPWM_Counter_Init(obj->tcpwm.base, _CYHAL_TCPWM_CNT_NUMBER(obj->tcpwm.resource), config);
145     }
146 
147     if (result == CY_RSLT_SUCCESS)
148     {
149         _cyhal_tcpwm_init_data(&obj->tcpwm);
150         Cy_TCPWM_Counter_Enable(obj->tcpwm.base, _CYHAL_TCPWM_CNT_NUMBER(obj->tcpwm.resource));
151     }
152 
153     return result;
154 }
155 
cyhal_timer_init(cyhal_timer_t * obj,cyhal_gpio_t pin,const cyhal_clock_t * clk)156 cy_rslt_t cyhal_timer_init(cyhal_timer_t *obj, cyhal_gpio_t pin, const cyhal_clock_t *clk)
157 {
158     CY_ASSERT(NULL != obj);
159 
160     // No support currently for pin connections on this device
161     if (CYHAL_NC_PIN_VALUE != pin)
162         return CYHAL_TIMER_RSLT_ERR_BAD_ARGUMENT;
163 
164     memset(obj, 0, sizeof(cyhal_timer_t));
165     cy_rslt_t result = CY_RSLT_SUCCESS;
166 
167     #if defined(COMPONENT_CAT5)
168     // T2Timer requested
169     if((uint32_t)clk == (uint32_t)(CYHAL_CLOCK_T2TIMER))
170     {
171         result = cyhal_hwmgr_allocate(CYHAL_RSC_T2TIMER, &obj->t2timer.resource);
172         if (CY_RSLT_SUCCESS == result)
173         {
174             obj->t2timer.which_timer = obj->t2timer.resource.block_num;
175             result = _cyhal_t2timer_init(&obj->t2timer, NULL);
176             if(result == CY_RSLT_SUCCESS)
177             {
178                 obj->is_t2timer = true;
179             }
180         }
181     }
182     else
183     {
184         // T2Timer not specifically requested, use either TCPWM or T2Timer
185     #endif
186         obj->tcpwm.resource.type = CYHAL_RSC_INVALID;
187         result = cyhal_hwmgr_allocate(CYHAL_RSC_TCPWM, &obj->tcpwm.resource);
188         if (CY_RSLT_SUCCESS == result)
189         {
190             result = _cyhal_timer_init_hw(obj, &_cyhal_timer_default_config, clk);
191     #if defined(COMPONENT_CAT5)
192             obj->is_t2timer = false;
193         }
194         else
195         {
196             result = cyhal_hwmgr_allocate(CYHAL_RSC_T2TIMER, &obj->t2timer.resource);
197             if (CY_RSLT_SUCCESS == result)
198             {
199                 obj->t2timer.which_timer = obj->t2timer.resource.block_num;
200                 result = _cyhal_t2timer_init(&obj->t2timer, NULL);
201                 if(result == CY_RSLT_SUCCESS)
202                 {
203                     obj->is_t2timer = true;
204                 }
205             }
206         }
207     #endif
208     }
209 
210     if (CY_RSLT_SUCCESS != result)
211     {
212         cyhal_timer_free(obj);
213     }
214 
215     return result;
216 }
217 
cyhal_timer_init_cfg(cyhal_timer_t * obj,const cyhal_timer_configurator_t * cfg)218 cy_rslt_t cyhal_timer_init_cfg(cyhal_timer_t *obj, const cyhal_timer_configurator_t *cfg)
219 {
220     memset(obj, 0, sizeof(cyhal_timer_t));
221     obj->tcpwm.resource = *cfg->resource;
222     obj->tcpwm.owned_by_configurator = true;
223     cy_rslt_t result = _cyhal_timer_init_hw(obj, cfg->config, cfg->clock);
224     #if defined(COMPONENT_CAT5)
225     // Device configurator doesn't currently support T2Timer
226     obj->is_t2timer = false;
227     #endif
228 
229     if(CY_RSLT_SUCCESS != result)
230     {
231         cyhal_timer_free(obj);
232     }
233     return result;
234 }
235 
cyhal_timer_configure(cyhal_timer_t * obj,const cyhal_timer_cfg_t * cfg)236 cy_rslt_t cyhal_timer_configure(cyhal_timer_t *obj, const cyhal_timer_cfg_t *cfg)
237 {
238     cy_rslt_t rslt;
239     #if defined(COMPONENT_CAT5)
240     if(obj->is_t2timer)
241     {
242         if((cfg->direction != CYHAL_TIMER_DIR_DOWN) || (cfg->is_compare != true) || (cfg->value != 0x0))
243         {
244             // T2Timer can only count down, it has no capture mode, and doesn't support starting values
245             return CYHAL_TIMER_RSLT_ERR_UNSUPPORTED;
246         }
247         cyhal_t2timer_cfg_t t2t_cfg = {
248             .mode = T2_ARM_TIMER_MODE_FREERUNNING,
249             .counter_mode = T2_ARM_TIMER_COUNTER_MODE_ONESHOT,
250             .duration = cfg->compare_value,
251         };
252         if(cfg->is_continuous)
253         {
254             t2t_cfg.counter_mode = T2_ARM_TIMER_COUNTER_MODE_WRAPPING;
255         }
256         rslt = _cyhal_t2timer_configure(&obj->t2timer, &t2t_cfg);
257     }
258     else
259     #endif
260     {
261         obj->default_value = cfg->value;
262         cy_stc_tcpwm_counter_config_t config = _cyhal_timer_default_config;
263         config.period = cfg->period;
264         config.compare0 = cfg->compare_value;
265         config.runMode = cfg->is_continuous ? CY_TCPWM_COUNTER_CONTINUOUS : CY_TCPWM_COUNTER_ONESHOT;
266         config.compareOrCapture = cfg->is_compare ? CY_TCPWM_COUNTER_MODE_COMPARE : CY_TCPWM_COUNTER_MODE_CAPTURE;
267         config.countDirection = _cyhal_timer_convert_direction(cfg->direction);
268         // DeInit will clear the interrupt mask; save it now and restore after we re-nit
269         uint32_t old_mask = Cy_TCPWM_GetInterruptMask(obj->tcpwm.base, _CYHAL_TCPWM_CNT_NUMBER(obj->tcpwm.resource));
270         Cy_TCPWM_Counter_DeInit(obj->tcpwm.base, _CYHAL_TCPWM_CNT_NUMBER(obj->tcpwm.resource), &config);
271         rslt = (cy_rslt_t)Cy_TCPWM_Counter_Init(obj->tcpwm.base, _CYHAL_TCPWM_CNT_NUMBER(obj->tcpwm.resource), &config);
272         Cy_TCPWM_Counter_Enable(obj->tcpwm.base, _CYHAL_TCPWM_CNT_NUMBER(obj->tcpwm.resource));
273         Cy_TCPWM_SetInterruptMask(obj->tcpwm.base, _CYHAL_TCPWM_CNT_NUMBER(obj->tcpwm.resource), old_mask);
274 
275         // This must be called after Cy_TCPWM_Counter_Init
276         cyhal_timer_reset(obj);
277     }
278 
279     return rslt;
280 }
281 
cyhal_timer_set_frequency(cyhal_timer_t * obj,uint32_t hz)282 cy_rslt_t cyhal_timer_set_frequency(cyhal_timer_t *obj, uint32_t hz)
283 {
284     cy_rslt_t result = CY_RSLT_SUCCESS;
285 
286     #if defined(COMPONENT_CAT5)
287     if(obj->is_t2timer)
288     {
289         result = _cyhal_t2timer_set_frequency(&obj->t2timer, hz);
290     }
291     else
292     #endif
293     {
294         if(!obj->tcpwm.dedicated_clock)
295         {
296             result = CYHAL_TIMER_RSLT_ERR_SHARED_CLOCK;
297         }
298         #if !defined(COMPONENT_CAT5)
299         const cyhal_clock_tolerance_t tolerance = {
300             .type = CYHAL_TOLERANCE_PERCENT,
301             .value = 2,
302         };
303         #endif
304         if(CY_RSLT_SUCCESS == result)
305         {
306             #if defined(COMPONENT_CAT5)
307             uint32_t current_freq = _cyhal_utils_get_peripheral_clock_frequency(&(obj->tcpwm.resource));
308             uint32_t divider = ((current_freq + hz - 1) / hz);
309             // _set_divider doesn't use this with CAT5, but to avoid warnings here is what it would use
310             en_clk_dst_t clk_dst = (en_clk_dst_t)(_CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(obj->tcpwm.resource.block_num)].clock_dst + obj->tcpwm.resource.channel_num);
311             if(CY_RSLT_SUCCESS == _cyhal_utils_peri_pclk_set_divider(clk_dst, &obj->tcpwm.clock, (divider - 1)))
312             #else
313             if((CY_RSLT_SUCCESS == cyhal_clock_set_enabled(&obj->tcpwm.clock, false, false)) &&
314             (CY_RSLT_SUCCESS == cyhal_clock_set_frequency(&obj->tcpwm.clock, hz, &tolerance)) &&
315             (CY_RSLT_SUCCESS == cyhal_clock_set_enabled(&obj->tcpwm.clock, true, false)))
316             #endif
317             {
318                 obj->tcpwm.clock_hz = cyhal_clock_get_frequency(&obj->tcpwm.clock);
319             }
320             else
321             {
322                 result = CYHAL_TIMER_RSLT_ERR_CLOCK_INIT;
323             }
324         }
325     }
326 
327     return result;
328 }
329 
cyhal_timer_start(cyhal_timer_t * obj)330 cy_rslt_t cyhal_timer_start(cyhal_timer_t *obj)
331 {
332     CY_ASSERT(NULL != obj);
333     cy_rslt_t result = CY_RSLT_SUCCESS;
334     #if (CYHAL_DRIVER_AVAILABLE_SYSPM)
335     #if defined(COMPONENT_CAT5)
336     if (_cyhal_tcpwm_pm_transition_pending() || (obj->is_t2timer && obj->running))
337     #else
338     if (_cyhal_tcpwm_pm_transition_pending())
339     #endif
340     {
341         return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
342     }
343     #endif
344 
345     #if defined(COMPONENT_CAT5)
346     if(obj->is_t2timer)
347     {
348         result = _cyhal_t2timer_start(&obj->t2timer);
349         if(result == CY_RSLT_SUCCESS)
350         {
351             obj->running = true;
352         }
353     }
354     else
355     #endif
356     {
357         Cy_TCPWM_Counter_Enable(obj->tcpwm.base, _CYHAL_TCPWM_CNT_NUMBER(obj->tcpwm.resource));
358         #if defined(CY_IP_MXTCPWM) && (CY_IP_MXTCPWM_VERSION >= 2)
359         Cy_TCPWM_TriggerStart_Single(obj->tcpwm.base, _CYHAL_TCPWM_CNT_NUMBER(obj->tcpwm.resource));
360         #else
361         Cy_TCPWM_TriggerStart(obj->tcpwm.base, (1 << _CYHAL_TCPWM_CNT_NUMBER(obj->tcpwm.resource)));
362         #endif
363     }
364     return result;
365 }
366 
cyhal_timer_stop(cyhal_timer_t * obj)367 cy_rslt_t cyhal_timer_stop(cyhal_timer_t *obj)
368 {
369     CY_ASSERT(NULL != obj);
370     cy_rslt_t result = CY_RSLT_SUCCESS;
371 
372     #if defined(COMPONENT_CAT5)
373     if(obj->is_t2timer)
374     {
375         result = _cyhal_t2timer_stop(&obj->t2timer);
376         if(result == CY_RSLT_SUCCESS)
377         {
378             obj->running = false;
379         }
380     }
381     else
382     #endif
383     {
384         Cy_TCPWM_Counter_Disable(obj->tcpwm.base, _CYHAL_TCPWM_CNT_NUMBER(obj->tcpwm.resource));
385     }
386 
387     return result;
388 }
389 
cyhal_timer_reset(cyhal_timer_t * obj)390 cy_rslt_t cyhal_timer_reset(cyhal_timer_t *obj)
391 {
392     CY_ASSERT(NULL != obj);
393     cy_rslt_t result = CY_RSLT_SUCCESS;
394 
395     #if defined(COMPONENT_CAT5)
396     if(obj->is_t2timer)
397     {
398         result = _cyhal_t2timer_reset(&obj->t2timer);
399         if(result == CY_RSLT_SUCCESS)
400         {
401             obj->running = true;
402         }
403     }
404     else
405     #endif
406     {
407         Cy_TCPWM_Counter_SetCounter(obj->tcpwm.base, _CYHAL_TCPWM_CNT_NUMBER(obj->tcpwm.resource), obj->default_value);
408     }
409 
410     return result;
411 }
412 
cyhal_timer_read(const cyhal_timer_t * obj)413 uint32_t cyhal_timer_read(const cyhal_timer_t *obj)
414 {
415     CY_ASSERT(NULL != obj);
416     uint32_t read_value = 0;
417     #if defined(COMPONENT_CAT5)
418     if(obj->is_t2timer)
419     {
420         read_value = _cyhal_t2timer_read(&obj->t2timer);
421     }
422     else
423     #endif
424     {
425         read_value = Cy_TCPWM_Counter_GetCounter(obj->tcpwm.base, _CYHAL_TCPWM_CNT_NUMBER(obj->tcpwm.resource));
426     }
427     return read_value;
428 }
429 
_cyhal_timer_translate_input_signal(cyhal_timer_input_t event)430 static cyhal_tcpwm_input_t _cyhal_timer_translate_input_signal(cyhal_timer_input_t event)
431 {
432     switch(event)
433     {
434         case CYHAL_TIMER_INPUT_START:
435             return CYHAL_TCPWM_INPUT_START;
436         case CYHAL_TIMER_INPUT_STOP:
437             return CYHAL_TCPWM_INPUT_STOP;
438         case CYHAL_TIMER_INPUT_RELOAD:
439             return CYHAL_TCPWM_INPUT_RELOAD;
440         case CYHAL_TIMER_INPUT_COUNT:
441             return CYHAL_TCPWM_INPUT_COUNT;
442         case CYHAL_TIMER_INPUT_CAPTURE:
443             return CYHAL_TCPWM_INPUT_CAPTURE;
444         default:
445             CY_ASSERT(false);
446             return (cyhal_tcpwm_input_t)0;
447     }
448 }
449 
_cyhal_timer_translate_output_signal(cyhal_timer_output_t signal)450 static cyhal_tcpwm_output_t _cyhal_timer_translate_output_signal(cyhal_timer_output_t signal)
451 {
452     switch(signal)
453     {
454         case CYHAL_TIMER_OUTPUT_OVERFLOW:
455             return CYHAL_TCPWM_OUTPUT_OVERFLOW;
456         case CYHAL_TIMER_OUTPUT_UNDERFLOW:
457             return CYHAL_TCPWM_OUTPUT_UNDERFLOW;
458         case CYHAL_TIMER_OUTPUT_COMPARE_MATCH:
459             return CYHAL_TCPWM_OUTPUT_COMPARE_MATCH;
460         case CYHAL_TIMER_OUTPUT_TERMINAL_COUNT:
461             return CYHAL_TCPWM_OUTPUT_TERMINAL_COUNT;
462         default:
463             CY_ASSERT(false);
464             return (cyhal_tcpwm_output_t)0;
465     }
466 }
467 
cyhal_timer_connect_digital2(cyhal_timer_t * obj,cyhal_source_t source,cyhal_timer_input_t signal,cyhal_edge_type_t edge_type)468 cy_rslt_t cyhal_timer_connect_digital2(cyhal_timer_t *obj, cyhal_source_t source, cyhal_timer_input_t signal, cyhal_edge_type_t edge_type)
469 {
470     #if defined(COMPONENT_CAT5)
471     if(obj->is_t2timer)
472     {
473         return CYHAL_TIMER_RSLT_ERR_UNSUPPORTED;
474     }
475     #endif
476     cyhal_tcpwm_input_t tcpwm_signal = _cyhal_timer_translate_input_signal(signal);
477     return _cyhal_tcpwm_connect_digital(&(obj->tcpwm), source, tcpwm_signal, edge_type);
478 }
479 
cyhal_timer_connect_digital(cyhal_timer_t * obj,cyhal_source_t source,cyhal_timer_input_t signal)480 cy_rslt_t cyhal_timer_connect_digital(cyhal_timer_t *obj, cyhal_source_t source, cyhal_timer_input_t signal)
481 {
482     #if defined(COMPONENT_CAT5)
483     if(obj->is_t2timer)
484     {
485         return CYHAL_TIMER_RSLT_ERR_UNSUPPORTED;
486     }
487     #endif
488 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
489     /* Signal type just tells us edge vs. level, but TCPWM lets you customize which edge you want. So default
490      * to rising edge. If the application cares about the edge type, it can use connect_digital2 */
491     cyhal_signal_type_t signal_type = _CYHAL_TRIGGER_GET_SOURCE_TYPE(source);
492     cyhal_edge_type_t edge_type = (signal_type == CYHAL_SIGNAL_TYPE_LEVEL) ? CYHAL_EDGE_TYPE_LEVEL : CYHAL_EDGE_TYPE_RISING_EDGE;
493     return cyhal_timer_connect_digital2(obj, source, signal, edge_type);
494 #else
495     CY_UNUSED_PARAMETER(obj);
496     CY_UNUSED_PARAMETER(source);
497     CY_UNUSED_PARAMETER(signal);
498     return CYHAL_TIMER_RSLT_ERR_BAD_ARGUMENT;
499 #endif
500 }
501 
cyhal_timer_enable_output(cyhal_timer_t * obj,cyhal_timer_output_t signal,cyhal_source_t * source)502 cy_rslt_t cyhal_timer_enable_output(cyhal_timer_t *obj, cyhal_timer_output_t signal, cyhal_source_t *source)
503 {
504     #if defined(COMPONENT_CAT5)
505     if(obj->is_t2timer)
506     {
507         return CYHAL_TIMER_RSLT_ERR_UNSUPPORTED;
508     }
509     #endif
510     cyhal_tcpwm_output_t tcpwm_signal = _cyhal_timer_translate_output_signal(signal);
511     return _cyhal_tcpwm_enable_output(&(obj->tcpwm), tcpwm_signal, source);
512 }
513 
cyhal_timer_disconnect_digital(cyhal_timer_t * obj,cyhal_source_t source,cyhal_timer_input_t signal)514 cy_rslt_t cyhal_timer_disconnect_digital(cyhal_timer_t *obj, cyhal_source_t source, cyhal_timer_input_t signal)
515 {
516     #if defined(COMPONENT_CAT5)
517     if(obj->is_t2timer)
518     {
519         return CYHAL_TIMER_RSLT_ERR_UNSUPPORTED;
520     }
521     #endif
522     return _cyhal_tcpwm_disconnect_digital(&(obj->tcpwm), source, _cyhal_timer_translate_input_signal(signal));
523 }
524 
cyhal_timer_disable_output(cyhal_timer_t * obj,cyhal_timer_output_t signal)525 cy_rslt_t cyhal_timer_disable_output(cyhal_timer_t *obj, cyhal_timer_output_t signal)
526 {
527     #if defined(COMPONENT_CAT5)
528     if(obj->is_t2timer)
529     {
530         return CYHAL_TIMER_RSLT_ERR_UNSUPPORTED;
531     }
532     #endif
533     return _cyhal_tcpwm_disable_output(&(obj->tcpwm), _cyhal_timer_translate_output_signal(signal));
534 }
535 
536 #if defined(__cplusplus)
537 }
538 #endif
539 
540 #endif /* CYHAL_DRIVER_AVAILABLE_TIMER */
541