1 /***************************************************************************//**
2 * \file cyhal_tcpwm_common.c
3 *
4 * \brief
5 * Code shared between the Cypress Timer/Counter and PWM.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2018-2022 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 #include "cyhal_hwmgr.h"
28 #include "cyhal_utils.h"
29 #include "cyhal_irq_impl.h"
30 #include "cyhal_syspm.h"
31 #include "cyhal_system.h"
32 #include "cyhal_tcpwm_common.h"
33 #include "cyhal_clock.h"
34
35 #if (_CYHAL_DRIVER_AVAILABLE_TCPWM)
36
37 #if defined(__cplusplus)
38 extern "C" {
39 #endif
40
41 #if defined(COMPONENT_CAT1B) || (COMPONENT_CAT1D)
42 #define TCPWM_CLOCK(block, channel) (PCLK_TCPWM##block##_CLOCK_COUNTER_EN##channel)
43 #elif defined(COMPONENT_CAT5)
44 /* Note: PCLK is not used on this device */
45 #define TCPWM_CLOCK(block, channel) (0)
46 #else
47 #define TCPWM_CLOCK(block, channel) (PCLK_TCPWM##block##_CLOCKS##channel)
48 #endif
49
50 #if defined(COMPONENT_CAT5)
51 /* Used to calculate which TCPWM_INTR_MASK_t to use when enabling interrupts */
52 #define _GET_TCPWM_INTR_MASK(group, counter) (1 << (((group) * 2) + counter))
53 #endif
54
55 #if defined(CY_IP_MXTCPWM_INSTANCES)
56 #if (CY_IP_MXTCPWM_VERSION == 1)
57 #if (CY_IP_MXTCPWM_INSTANCES == 0)
58 #define _CYHAL_TCPWM_CHANNELS (0u)
59 #elif (CY_IP_MXTCPWM_INSTANCES == 1)
60 #define _CYHAL_TCPWM_CHANNELS (TCPWM0_CNT_NR)
61 #elif (CY_IP_MXTCPWM_INSTANCES == 2)
62 #define _CYHAL_TCPWM_CHANNELS (TCPWM0_CNT_NR + TCPWM1_CNT_NR)
63 #else
64 #warning Unhandled TCPWM instance count
65 #endif
66 #else // (CY_IP_MXTCPWM_VERSION >= 2)
67 #if (CY_IP_MXTCPWM_INSTANCES == 1)
68 #if (TCPWM_GRP_NR == 0)
69 #define _CYHAL_TCPWM_CHANNELS (0U)
70 #elif (TCPWM_GRP_NR == 1)
71 #define _CYHAL_TCPWM_CHANNELS (TCPWM_GRP_NR0_GRP_GRP_CNT_NR)
72 #elif (TCPWM_GRP_NR == 2)
73 #define _CYHAL_TCPWM_CHANNELS (TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR)
74 #elif (TCPWM_GRP_NR == 3)
75 #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)
76 #elif (TCPWM_GRP_NR == 4)
77 #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)
78 #endif
79 #elif (CY_IP_MXTCPWM_INSTANCES == 2)
80 #if (TCPWM0_GRP_NR == 0)
81 #define _CYHAL_TCPWM0_CHANNELS (0U)
82 #elif (TCPWM0_GRP_NR == 1)
83 #define _CYHAL_TCPWM0_CHANNELS (TCPWM0_GRP_NR0_GRP_GRP_CNT_NR)
84 #elif (TCPWM0_GRP_NR == 2)
85 #define _CYHAL_TCPWM0_CHANNELS (TCPWM0_GRP_NR0_GRP_GRP_CNT_NR + TCPWM0_GRP_NR1_GRP_GRP_CNT_NR)
86 #elif (TCPWM0_GRP_NR == 3)
87 #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)
88 #elif (TCPWM0_GRP_NR == 4)
89 #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)
90 #endif
91 #ifndef _CYHAL_TCPWM0_CHANNELS
92 #error "Unhandled TCPWM0_GRP_NR count"
93 #endif
94 #if (TCPWM1_GRP_NR == 0)
95 #define _CYHAL_TCPWM1_CHANNELS (0U)
96 #elif (TCPWM1_GRP_NR == 1)
97 #define _CYHAL_TCPWM1_CHANNELS (TCPWM1_GRP_NR0_GRP_GRP_CNT_NR)
98 #elif (TCPWM1_GRP_NR == 2)
99 #define _CYHAL_TCPWM1_CHANNELS (TCPWM1_GRP_NR0_GRP_GRP_CNT_NR + TCPWM1_GRP_NR1_GRP_GRP_CNT_NR)
100 #elif (TCPWM1_GRP_NR == 3)
101 #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)
102 #elif (TCPWM1_GRP_NR == 4)
103 #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)
104 #endif
105 #ifndef _CYHAL_TCPWM1_CHANNELS
106 #error "Unhandled TCPWM1_GRP_NR count"
107 #endif
108
109 #define _CYHAL_TCPWM_CHANNELS (_CYHAL_TCPWM0_CHANNELS + _CYHAL_TCPWM1_CHANNELS)
110 #else
111 #warning Unhandled TCPWM instance count
112 #endif
113 #endif
114 #elif defined(CY_IP_M0S8TCPWM_INSTANCES)
115 #if (CY_IP_M0S8TCPWM_INSTANCES == 1)
116 #define _CYHAL_TCPWM_CHANNELS (TCPWM_CNT_NR)
117 #else
118 #warning Unhandled TCPWM instance count
119 #endif
120 #endif
121
122 const _cyhal_tcpwm_data_t _CYHAL_TCPWM_DATA[] =
123 {
124 #if defined(CY_IP_MXTCPWM_INSTANCES)
125 #if (CY_IP_MXTCPWM_VERSION == 1)
126 #if (CY_IP_MXTCPWM_INSTANCES > 0)
127 {TCPWM0, TCPWM_CLOCK(0, 0), TCPWM0_CNT_CNT_WIDTH, TCPWM0_CNT_NR, 0, tcpwm_0_interrupts_0_IRQn },
128 #endif
129 #if (CY_IP_MXTCPWM_INSTANCES > 1)
130 {TCPWM1, TCPWM_CLOCK(1, 0), TCPWM1_CNT_CNT_WIDTH, TCPWM1_CNT_NR, TCPWM0_CNT_NR, tcpwm_1_interrupts_0_IRQn },
131 #endif
132 #if (CY_IP_MXTCPWM_INSTANCES > 2)
133 #warning Unhandled TCPWM instance count
134 #endif
135 #else // (CY_IP_MXTCPWM_VERSION >= 2)
136 #if (CY_IP_MXTCPWM_INSTANCES == 1)
137 #if (TCPWM_GRP_NR > 0)
138 {TCPWM0, TCPWM_CLOCK(0, 0), TCPWM_GRP_NR0_CNT_GRP_CNT_WIDTH, TCPWM_GRP_NR0_GRP_GRP_CNT_NR, 0, tcpwm_0_interrupts_0_IRQn },
139 #endif
140 #if (TCPWM_GRP_NR > 1)
141 {TCPWM0, TCPWM_CLOCK(0, 256), TCPWM_GRP_NR1_CNT_GRP_CNT_WIDTH, TCPWM_GRP_NR1_GRP_GRP_CNT_NR, TCPWM_GRP_NR0_GRP_GRP_CNT_NR, tcpwm_0_interrupts_256_IRQn },
142 #endif
143 #if (TCPWM_GRP_NR > 2)
144 {TCPWM0, TCPWM_CLOCK(0, 512), TCPWM_GRP_NR2_CNT_GRP_CNT_WIDTH, TCPWM_GRP_NR2_GRP_GRP_CNT_NR, TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR, tcpwm_0_interrupts_512_IRQn },
145 #endif
146 #if (TCPWM_GRP_NR > 3)
147 {TCPWM0, TCPWM_CLOCK(0, 768), TCPWM_GRP_NR3_CNT_GRP_CNT_WIDTH, TCPWM_GRP_NR3_GRP_GRP_CNT_NR, TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR + TCPWM_GRP_NR2_GRP_GRP_CNT_NR, tcpwm_0_interrupts_768_IRQn },
148 #endif
149 #endif
150 #if (CY_IP_MXTCPWM_INSTANCES == 2)
151 #if (TCPWM0_GRP_NR > 0)
152 {TCPWM0, TCPWM_CLOCK(0, 0), TCPWM0_GRP_NR0_CNT_GRP_CNT_WIDTH, TCPWM0_GRP_NR0_GRP_GRP_CNT_NR, 0, tcpwm_0_interrupts_0_IRQn },
153 #endif
154 #if (TCPWM0_GRP_NR > 1)
155 {TCPWM0, TCPWM_CLOCK(0, 256), TCPWM0_GRP_NR1_CNT_GRP_CNT_WIDTH, TCPWM0_GRP_NR1_GRP_GRP_CNT_NR, TCPWM0_GRP_NR0_GRP_GRP_CNT_NR, tcpwm_0_interrupts_256_IRQn },
156 #endif
157 #if (TCPWM0_GRP_NR > 2)
158 {TCPWM0, TCPWM_CLOCK(0, 512), TCPWM0_GRP_NR2_CNT_GRP_CNT_WIDTH, TCPWM0_GRP_NR2_GRP_GRP_CNT_NR, TCPWM0_GRP_NR0_GRP_GRP_CNT_NR + TCPWM0_GRP_NR1_GRP_GRP_CNT_NR, tcpwm_0_interrupts_512_IRQn },
159 #endif
160 #if (TCPWM0_GRP_NR > 3)
161 {TCPWM0, TCPWM_CLOCK(0, 768), TCPWM0_GRP_NR3_CNT_GRP_CNT_WIDTH, TCPWM0_GRP_NR3_GRP_GRP_CNT_NR, TCPWM0_GRP_NR0_GRP_GRP_CNT_NR + TCPWM0_GRP_NR1_GRP_GRP_CNT_NR + TCPWM0_GRP_NR2_GRP_GRP_CNT_NR, tcpwm_0_interrupts_768_IRQn },
162 #endif
163 #if (TCPWM0_GRP_NR > 4)
164 #error "Unhandled TCPWM0_GRP_NR count"
165 #endif
166 #if (TCPWM1_GRP_NR > 0)
167 {TCPWM1, TCPWM_CLOCK(1, 0), TCPWM1_GRP_NR0_CNT_GRP_CNT_WIDTH, TCPWM1_GRP_NR0_GRP_GRP_CNT_NR, _CYHAL_TCPWM0_CHANNELS, tcpwm_1_interrupts_0_IRQn },
168 #endif
169 #if (TCPWM1_GRP_NR > 1)
170 {TCPWM1, TCPWM_CLOCK(1, 256), TCPWM1_GRP_NR1_CNT_GRP_CNT_WIDTH, TCPWM1_GRP_NR1_GRP_GRP_CNT_NR, _CYHAL_TCPWM0_CHANNELS + TCPWM1_GRP_NR0_GRP_GRP_CNT_NR, tcpwm_1_interrupts_256_IRQn },
171 #endif
172 #if (TCPWM1_GRP_NR > 2)
173 {TCPWM1, TCPWM_CLOCK(1, 512), TCPWM1_GRP_NR2_CNT_GRP_CNT_WIDTH, TCPWM1_GRP_NR2_GRP_GRP_CNT_NR, _CYHAL_TCPWM0_CHANNELS + TCPWM1_GRP_NR0_GRP_GRP_CNT_NR + TCPWM1_GRP_NR1_GRP_GRP_CNT_NR, tcpwm_1_interrupts_512_IRQn },
174 #endif
175 #if (TCPWM1_GRP_NR > 3)
176 {TCPWM1, TCPWM_CLOCK(1, 768), TCPWM1_GRP_NR3_CNT_GRP_CNT_WIDTH, TCPWM1_GRP_NR3_GRP_GRP_CNT_NR, _CYHAL_TCPWM0_CHANNELS + TCPWM1_GRP_NR0_GRP_GRP_CNT_NR + TCPWM1_GRP_NR1_GRP_GRP_CNT_NR + TCPWM1_GRP_NR2_GRP_GRP_CNT_NR, tcpwm_1_interrupts_768_IRQn },
177 #endif
178 #if (TCPWM1_GRP_NR > 4)
179 #error "Unhandled TCPWM1_GRP_NR count"
180 #endif
181 #endif
182 #if (CY_IP_MXTCPWM_INSTANCES > 2)
183 #warning Unhandled TCPWM instance count
184 #endif
185 #endif
186 #elif defined(CY_IP_M0S8TCPWM_INSTANCES)
187 #if (CY_IP_M0S8TCPWM_INSTANCES == 1)
188 {TCPWM, PCLK_TCPWM_CLOCKS0, 16, TCPWM_CNT_NR, 0, tcpwm_interrupts_0_IRQn },
189 #endif
190 #if (CY_IP_M0S8TCPWM_INSTANCES > 1)
191 #warning Unhandled TCPWM instance count
192 #endif
193 #endif
194 };
195
196
197 // There are some number of input trigger indices (starting at 0) that are
198 // reserved for various purposes. Here we are dealing with inputs from the
199 // trigmux which start after the reserved inputs so we must always offset the
200 // trigger index after reservation. For all devices, indices 0 and 1 are
201 // reserved for constant signals 0 and 1 respectively (so offset by 2 to
202 // start). Depending on device, further offsetting may be needed as well. The
203 // number of trigmux tcpwm inputs (but not the total number of tcpwm trigger
204 // inputs) per tcpwm block is also defined here.
205 #if (CY_IP_MXTCPWM_VERSION == 1U)
206 const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1] = {2};
207 const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1] = {(16 - 2)}; // = {(16 - _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[0])};
208 #elif (CY_IP_MXTCPWM_VERSION == 2U)
209 // Note: These devices also have support for up to 256 trigger lines total,
210 // but only 28 input triggers (on top of the 2 + TCPWM_TR_ONE_CNT_NR) are
211 // currently available, so we only support that to save RAM.
212 #if (CY_IP_MXTCPWM_INSTANCES == 1)
213 const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1] = {(2 + TCPWM_TR_ONE_CNT_NR)};
214 const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1] = {(TCPWM_TR_ALL_CNT_NR)};
215 #elif (CY_IP_MXTCPWM_INSTANCES == 2)
216 const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[2] = {(2 + TCPWM0_TR_ONE_CNT_NR), (2 + TCPWM1_TR_ONE_CNT_NR)};
217 const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[2] = {(TCPWM0_TR_ALL_CNT_NR), (TCPWM1_TR_ALL_CNT_NR)};
218 #else
219 #warning Unhandled TCPWM instance count
220 #endif
221 #else // (CY_IP_M0S8TCPWM_VERSION == 2)
222 #if defined(CY_DEVICE_PSOC4AS1)
223 const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1] = {(2 + 12)};
224 const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1] = {(16 - 2 - 12)}; // = {(16 - _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[0])};
225 #else
226 const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1] = {(2 + 7)};
227 const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1] = {(16 - 2 - 7)}; // = {(16 - _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[0])};
228 #endif
229 #endif
230
231 // Get the the channel relative to the start of the first TCPWM IP block
232 #define _CYHAL_TCPWM_GET_ARRAY_INDEX(block, channel) ((_CYHAL_TCPWM_DATA[(_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block))].channel_offset) + (channel))
233
234 #if (CY_IP_MXTCPWM_VERSION == 2)
235 #if (CY_IP_MXTCPWM_INSTANCES == 1)
236 uint8_t _CYHAL_OUTPUT_TRIGGERS_USED [_CYHAL_TCPWM_CHANNELS];
237 #elif (CY_IP_MXTCPWM_INSTANCES == 2)
238 uint8_t _CYHAL_OUTPUT_TRIGGERS_USED [_CYHAL_TCPWM0_CHANNELS + _CYHAL_TCPWM1_CHANNELS];
239 #else
240 #warning Unhandled TCPWM instance count
241 #endif // (CY_IP_MXTCPWM_INSTANCES == 1 or 2)
242 #endif // (CY_IP_MXTCPWM_VERSION == 2)
243
244 /** Callback array for TCPWM interrupts */
245 static cyhal_tcpwm_t *_cyhal_tcpwm_data_structs[_CYHAL_TCPWM_CHANNELS];
246
247 #if (CYHAL_DRIVER_AVAILABLE_SYSPM)
_cyhal_tcpwm_pm_has_enabled(void)248 static bool _cyhal_tcpwm_pm_has_enabled(void)
249 {
250 for (uint8_t i = 0; i < _CYHAL_TCPWM_CHANNELS; i++)
251 {
252 if (NULL != _cyhal_tcpwm_data_structs[i])
253 {
254 return true;
255 }
256 }
257 return false;
258 }
259
260 static bool _cyhal_tcpwm_pm_transition_pending_value = false;
261
_cyhal_tcpwm_pm_transition_pending(void)262 bool _cyhal_tcpwm_pm_transition_pending(void)
263 {
264 return _cyhal_tcpwm_pm_transition_pending_value;
265 }
266
_cyhal_tcpwm_pm_callback(cyhal_syspm_callback_state_t state,cyhal_syspm_callback_mode_t mode,void * callback_arg)267 static bool _cyhal_tcpwm_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
268 {
269 CY_UNUSED_PARAMETER(state);
270 CY_UNUSED_PARAMETER(callback_arg);
271 switch(mode)
272 {
273 case CYHAL_SYSPM_CHECK_FAIL:
274 {
275 _cyhal_tcpwm_pm_transition_pending_value = false;
276 break;
277 }
278 case CYHAL_SYSPM_BEFORE_TRANSITION:
279 {
280 for (uint8_t i = 0; i < _CYHAL_TCPWM_INSTANCES; i++)
281 {
282 TCPWM_Type* base = _CYHAL_TCPWM_DATA[i].base;
283 for (uint8_t j = 0; j < _CYHAL_TCPWM_DATA[i].num_channels; j++)
284 {
285 // Not using _CYHAL_TCPWM_GET_ARRAY_INDEX macro since we've already compressed the indexing (skipping empty groups),
286 // and the macro would compress it again
287 if (NULL != _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j])
288 {
289 #if defined(CY_IP_M0S8TCPWM) || (CY_IP_MXTCPWM_VERSION == 1)
290 uint32_t mask = ((uint32_t)1u << j);
291 if((((TCPWM_Type *)(base))->CTRL) & mask)
292 {
293 _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j]->presleep_state = true;
294 }
295 else
296 {
297 _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j]->presleep_state = false;
298 }
299 #else
300 if(_FLD2BOOL(TCPWM_GRP_CNT_V2_CTRL_ENABLED, TCPWM_GRP_CNT_CTRL(base, TCPWM_GRP_CNT_GET_GRP(j), j)))
301 {
302 _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j]->presleep_state = true;
303 }
304 else
305 {
306 _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j]->presleep_state = false;
307 }
308 #endif
309 }
310 }
311 }
312 break;
313 }
314 case CYHAL_SYSPM_AFTER_TRANSITION:
315 {
316 for (uint8_t i = 0; i < _CYHAL_TCPWM_INSTANCES; i++)
317 {
318 #if defined(CY_IP_M0S8TCPWM) || (CY_IP_MXTCPWM_VERSION == 1)
319 uint32_t enable_flag = 0;
320 #endif
321 TCPWM_Type* base = _CYHAL_TCPWM_DATA[i].base;
322 for (uint8_t j = 0; j < _CYHAL_TCPWM_DATA[i].num_channels; j++)
323 {
324 // Not using _CYHAL_TCPWM_GET_ARRAY_INDEX macro since we've already compressed the indexing (skipping empty groups),
325 // and the macro would compress it again
326 if (NULL != _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j])
327 {
328
329 if(_cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j]->presleep_state)
330 {
331 #if defined(CY_IP_M0S8TCPWM) || (CY_IP_MXTCPWM_VERSION == 1)
332 enable_flag |= 1u << j;
333 #else
334 Cy_TCPWM_Enable_Single(base, j);
335 #endif
336 }
337 }
338 }
339 #if defined(CY_IP_M0S8TCPWM) || (CY_IP_MXTCPWM_VERSION == 1)
340 if (0 != enable_flag)
341 {
342 // This only enables the counter. This does not start the timer/counter or the pwm.
343 Cy_TCPWM_Enable_Multiple(base, enable_flag);
344 }
345 #endif
346 }
347 _cyhal_tcpwm_pm_transition_pending_value = false;
348 break;
349 }
350 case CYHAL_SYSPM_CHECK_READY:
351 {
352 for (uint8_t i = 0; i < _CYHAL_TCPWM_INSTANCES; i++)
353 {
354 for (uint8_t j = 0; j < _CYHAL_TCPWM_DATA[i].num_channels; j++)
355 {
356 // Not using _CYHAL_TCPWM_GET_ARRAY_INDEX macro since we've already compressed the indexing (skipping empty groups),
357 // and the macro would compress it again
358 cyhal_tcpwm_t* obj = _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_DATA[i].channel_offset + j];
359 if ((NULL != obj) && (CY_TCPWM_PWM_STATUS_COUNTER_RUNNING & Cy_TCPWM_PWM_GetStatus(obj->base, _CYHAL_TCPWM_CNT_NUMBER(obj->resource))))
360 {
361 return false;
362 }
363 }
364 }
365 _cyhal_tcpwm_pm_transition_pending_value = true;
366 break;
367 }
368 default:
369 {
370 CY_ASSERT(false);
371 break;
372 }
373 }
374 return true;
375 }
376
377 static cyhal_syspm_callback_data_t _cyhal_tcpwm_syspm_callback_data =
378 {
379 .callback = &_cyhal_tcpwm_pm_callback,
380 .states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_CPU_DEEPSLEEP_RAM | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE),
381 .next = NULL,
382 .args = NULL,
383 .ignore_modes = (cyhal_syspm_callback_mode_t)(CYHAL_SYSPM_AFTER_DS_WFI_TRANSITION),
384 };
385
386 #else /* !(CYHAL_DRIVER_AVAILABLE_SYSPM) */
387 /* If SysPm driver is not available redefine function for TCPWM to return a bad value */
_cyhal_tcpwm_pm_transition_pending(void)388 bool _cyhal_tcpwm_pm_transition_pending(void)
389 {
390 return false;
391 }
392 #endif /* (CYHAL_DRIVER_AVAILABLE_SYSPM) */
393
_cyhal_tcpwm_init_data(cyhal_tcpwm_t * tcpwm)394 void _cyhal_tcpwm_init_data(cyhal_tcpwm_t *tcpwm)
395 {
396 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
397 for (uint8_t i = 0; i < _CYHAL_TCPWM_INPUTS; i++)
398 {
399 tcpwm->inputs[i] = CYHAL_TRIGGER_CPUSS_ZERO;
400 }
401 #endif
402 #if (CYHAL_DRIVER_AVAILABLE_SYSPM)
403 if (!_cyhal_tcpwm_pm_has_enabled())
404 {
405 _cyhal_syspm_register_peripheral_callback(&_cyhal_tcpwm_syspm_callback_data);
406 }
407 #endif
408 _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_GET_ARRAY_INDEX(tcpwm->resource.block_num, tcpwm->resource.channel_num)] = tcpwm;
409 }
410
411 #if defined (COMPONENT_CAT5)
_cyhal_tcpwm_irq_handler(UINT8 group_id,UINT8 counter_id)412 static void _cyhal_tcpwm_irq_handler(UINT8 group_id, UINT8 counter_id)
413 {
414 uint8_t block = group_id;
415 uint8_t channel = counter_id;
416 #else
417 static void _cyhal_tcpwm_irq_handler(void)
418 {
419 _cyhal_system_irq_t irqn = _cyhal_irq_get_active();
420 uint8_t block, channel = 0;
421 // Determine TCPWM block and channel from IRQn
422 for (block = 0; block < _CYHAL_TCPWM_INSTANCES; block++)
423 {
424 if ((irqn >= _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block)].isr_offset) && (irqn < _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block)].isr_offset + _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block)].num_channels))
425 {
426 channel = (uint8_t)(irqn - _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block)].isr_offset);
427 break;
428 }
429 }
430 #endif
431
432 if (block < _CYHAL_TCPWM_INSTANCES)
433 {
434 TCPWM_Type *blockAddr = _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block)].base;
435 cyhal_tcpwm_t *tcpwm = _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_GET_ARRAY_INDEX(block, channel)];
436 #if (_CYHAL_IRQ_MUXING)
437 /* Disable any interrupts that couldn't be disabled from enable_event */
438 uint32_t saved_intr_status = cyhal_system_critical_section_enter();
439 if(0u != tcpwm->clear_intr_mask)
440 {
441 uint32_t cnt_num = _CYHAL_TCPWM_CNT_NUMBER(tcpwm->resource);
442 uint32_t old_mask = Cy_TCPWM_GetInterruptMask(blockAddr, cnt_num);
443 Cy_TCPWM_SetInterruptMask(blockAddr, cnt_num, (old_mask & ~(tcpwm->clear_intr_mask)));
444 tcpwm->clear_intr_mask = 0u;
445 }
446 cyhal_system_critical_section_exit(saved_intr_status);
447 #endif
448 uint32_t intrCause = Cy_TCPWM_GetInterruptStatusMasked(blockAddr, _CYHAL_TCPWM_CNT_NUMBER(tcpwm->resource));
449 /* The masked status can be 0 if we updated the mask above */
450 if (0u != intrCause && tcpwm->callback_data.callback != NULL)
451 {
452 _cyhal_tcpwm_event_callback_t callback = (_cyhal_tcpwm_event_callback_t) tcpwm->callback_data.callback;
453 /* Call registered callbacks here */
454 (void) (callback) (tcpwm->callback_data.callback_arg, intrCause);
455 }
456
457 Cy_TCPWM_ClearInterrupt(blockAddr, _CYHAL_TCPWM_CNT_NUMBER(tcpwm->resource), intrCause);
458
459 #if defined(COMPONENT_CAT5)
460 // CAT5 interrupt disables itself after firing, re-enable it
461 Cy_TCPWM_EnableInterrupt(_GET_TCPWM_INTR_MASK(group_id, counter_id));
462 #endif
463 }
464 else
465 {
466 CY_HALT(); // Could not determine the block/channel for IRQn
467 }
468 }
469
470 /*******************************************************************************
471 * TCPWM Shared HAL Functions
472 *******************************************************************************/
473
474 void _cyhal_tcpwm_free(cyhal_tcpwm_t *obj)
475 {
476 CY_ASSERT(NULL != obj);
477
478 _cyhal_system_irq_t irqn = (_cyhal_system_irq_t)(_CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(obj->resource.block_num)].isr_offset + obj->resource.channel_num);
479 _cyhal_irq_free(irqn);
480
481 if (NULL != obj->base)
482 {
483 _cyhal_tcpwm_data_structs[_CYHAL_TCPWM_GET_ARRAY_INDEX(obj->resource.block_num, obj->resource.channel_num)] = NULL;
484 #if (CYHAL_DRIVER_AVAILABLE_SYSPM)
485 if (!_cyhal_tcpwm_pm_has_enabled())
486 {
487 _cyhal_syspm_unregister_peripheral_callback(&_cyhal_tcpwm_syspm_callback_data);
488 }
489 #endif
490
491 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
492 for (uint8_t i = 0; i < _CYHAL_TCPWM_OUTPUTS; i++)
493 {
494 _cyhal_tcpwm_disable_output(obj, (cyhal_tcpwm_output_t)i);
495 }
496 for (uint8_t i = 0; i < _CYHAL_TCPWM_INPUTS; i++)
497 {
498 if (CYHAL_TRIGGER_CPUSS_ZERO != obj->inputs[i])
499 {
500 _cyhal_tcpwm_disconnect_digital(obj, obj->inputs[i], (cyhal_tcpwm_input_t)i);
501 }
502 }
503 #endif
504
505 #if defined(CY_IP_MXTCPWM) && (CY_IP_MXTCPWM_VERSION >= 2)
506 Cy_TCPWM_Disable_Single(obj->base, _CYHAL_TCPWM_CNT_NUMBER(obj->resource));
507 #else
508 Cy_TCPWM_PWM_Disable(obj->base, _CYHAL_TCPWM_CNT_NUMBER(obj->resource));
509 #endif
510
511 if(false == obj->owned_by_configurator)
512 {
513 cyhal_hwmgr_free(&(obj->resource));
514 }
515
516 obj->base = NULL;
517 obj->resource.type = CYHAL_RSC_INVALID;
518 }
519
520 if (obj->dedicated_clock)
521 {
522 en_clk_dst_t pclk = (en_clk_dst_t)(_CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(obj->resource.block_num)].clock_dst + obj->resource.channel_num);
523 cy_rslt_t rslt = _cyhal_utils_peri_pclk_disable_divider(pclk, &(obj->clock));
524 CY_UNUSED_PARAMETER(rslt); /* CY_ASSERT only processes in DEBUG, ignores for others */
525 CY_ASSERT(CY_RSLT_SUCCESS == rslt);
526 cyhal_clock_free(&(obj->clock));
527 obj->dedicated_clock = false;
528 }
529 }
530
531 void _cyhal_tcpwm_register_callback(cyhal_resource_inst_t *resource, cy_israddress callback, void *callback_arg)
532 {
533 uint8_t index = _CYHAL_TCPWM_GET_ARRAY_INDEX(resource->block_num, resource->channel_num);
534 uint32_t savedIntrStatus = cyhal_system_critical_section_enter();
535 _cyhal_tcpwm_data_structs[index]->callback_data.callback = callback;
536 _cyhal_tcpwm_data_structs[index]->callback_data.callback_arg = callback_arg;
537 cyhal_system_critical_section_exit(savedIntrStatus);
538
539 _cyhal_system_irq_t irqn = (_cyhal_system_irq_t)(_CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(resource->block_num)].isr_offset + resource->channel_num);
540 /* Only enable if it's not already enabled */
541 if (false == _cyhal_irq_is_enabled(irqn))
542 {
543 #if defined (COMPONENT_CAT5)
544 Cy_TCPWM_RegisterInterruptCallback(_cyhal_tcpwm_irq_handler);
545 Cy_TCPWM_EnableInterrupt(_GET_TCPWM_INTR_MASK(resource->block_num, resource->channel_num));
546 #endif
547
548 _cyhal_irq_register(irqn, CYHAL_ISR_PRIORITY_DEFAULT, (cy_israddress)_cyhal_tcpwm_irq_handler);
549 _cyhal_irq_enable(irqn);
550 }
551 }
552
553 void _cyhal_tcpwm_enable_event(cyhal_tcpwm_t *tcpwm, cyhal_resource_inst_t *resource, uint32_t event, uint8_t intr_priority, bool enable)
554 {
555 uint32_t old_mask = Cy_TCPWM_GetInterruptMask(tcpwm->base, _CYHAL_TCPWM_CNT_NUMBER(*resource));
556 if (enable)
557 {
558 // Clear any newly enabled events so that old IRQs don't trigger ISRs
559 Cy_TCPWM_ClearInterrupt(tcpwm->base, _CYHAL_TCPWM_CNT_NUMBER(*resource), ~old_mask & event);
560 }
561 #if (_CYHAL_IRQ_MUXING)
562 /* We may be in a critical section. Only clear the interrupt status if there isn't a pending interrupt */
563 if (Cy_TCPWM_GetInterruptStatus(tcpwm->base, _CYHAL_TCPWM_CNT_NUMBER(*resource)) == 0 || enable)
564 #endif
565 {
566 Cy_TCPWM_SetInterruptMask(tcpwm->base, _CYHAL_TCPWM_CNT_NUMBER(*resource), enable ? (old_mask | event) : (old_mask & ~event));
567 }
568 #if (_CYHAL_IRQ_MUXING)
569 else
570 {
571 /* Note that this interrupt cause should be cleared the next time an interrupt is triggered */
572 uint32_t saved_intr_status = cyhal_system_critical_section_enter();
573 tcpwm->clear_intr_mask |= event;
574 cyhal_system_critical_section_exit(saved_intr_status);
575 }
576 #endif
577
578 _cyhal_system_irq_t irqn = (_cyhal_system_irq_t) (_CYHAL_TCPWM_DATA[_CYHAL_TCPWM_ADJUST_BLOCK_INDEX(resource->block_num)].isr_offset + resource->channel_num);
579 _cyhal_irq_set_priority(irqn, intr_priority);
580 }
581
582 #if (CY_IP_MXTCPWM_VERSION == 2U)
583 static uint8_t _cyhal_tcpwm_convert_output_t(cyhal_tcpwm_output_t signal)
584 {
585 switch(signal)
586 {
587 case CYHAL_TCPWM_OUTPUT_OVERFLOW:
588 return CY_TCPWM_CNT_TRIGGER_ON_OVERFLOW;
589 case CYHAL_TCPWM_OUTPUT_UNDERFLOW:
590 return CY_TCPWM_CNT_TRIGGER_ON_UNDEFLOW;
591 case CYHAL_TCPWM_OUTPUT_TERMINAL_COUNT:
592 return CY_TCPWM_CNT_TRIGGER_ON_TC;
593 case CYHAL_TCPWM_OUTPUT_COMPARE_MATCH:
594 return CY_TCPWM_CNT_TRIGGER_ON_CC0_MATCH;
595 case CYHAL_TCPWM_OUTPUT_LINE_OUT:
596 return CY_TCPWM_CNT_TRIGGER_ON_LINE_OUT;
597 default:
598 CY_ASSERT(false);
599 return 0;
600 }
601 }
602 #endif
603
604 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
605 #if (CY_IP_MXTCPWM_VERSION == 1U) ||(CY_IP_MXTCPWM_VERSION == 2U) || (CY_IP_M0S8TCPWM_VERSION == 2)
606 // Assumes trig_index is not offset by _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET
607 // (that is, it is 0 indexed).
608 cyhal_dest_t _cyhal_tpwm_calculate_dest(uint8_t block, uint8_t trig_index)
609 {
610 #if (CY_IP_MXTCPWM_VERSION == 1U)
611 if(block == 0)
612 {
613 return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM0_TR_IN0 + trig_index);
614 }
615 else
616 {
617 CY_ASSERT(block == 1);
618 return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM1_TR_IN0 + trig_index);
619 }
620 #elif (CY_IP_MXTCPWM_VERSION == 2U)
621 #if (CY_IP_MXTCPWM_INSTANCES == 2)
622 return (cyhal_dest_t)(_CYHAL_TCPWM_GET_IP_BLOCK(block) == 0 ? (CYHAL_TRIGGER_TCPWM0_TR_ALL_CNT_IN0 + \
623 trig_index) : (CYHAL_TRIGGER_TCPWM1_TR_ALL_CNT_IN0 + trig_index));
624 #else
625 CY_UNUSED_PARAMETER(block);
626 return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM0_TR_ALL_CNT_IN0 + trig_index);
627 #endif
628 #elif (CY_IP_M0S8TCPWM_VERSION == 2)
629 CY_UNUSED_PARAMETER(block);
630 #if defined(CY_DEVICE_PSOC4AS1)
631 CY_ASSERT(block == 0);
632 return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM_TR_IN12 + trig_index);
633 #elif defined(CY_DEVICE_PMG1S3) || defined(CY_DEVICE_CCG7S)
634 CY_ASSERT(block == 0);
635 return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM_TR_IN8 + trig_index);
636 #else
637 CY_ASSERT(block == 0);
638 return (cyhal_dest_t)(CYHAL_TRIGGER_TCPWM_TR_IN7 + trig_index);
639 #endif
640 #endif
641 }
642 #endif
643
644 #if (CY_IP_MXTCPWM_VERSION == 1U) || (CY_IP_M0S8TCPWM_VERSION == 2)
645 static cyhal_source_t _cyhal_tcpwm_calculate_source(uint8_t block, uint8_t chnl, cyhal_tcpwm_output_t signal)
646 {
647 #if (CY_IP_MXTCPWM_VERSION == 1U)
648 switch(signal)
649 {
650 case CYHAL_TCPWM_OUTPUT_OVERFLOW:
651 return block == 0
652 ? (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_OVERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE)
653 : (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM1_TR_OVERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
654 case CYHAL_TCPWM_OUTPUT_UNDERFLOW:
655 return block == 0
656 ? (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_UNDERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE)
657 : (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM1_TR_UNDERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
658 case CYHAL_TCPWM_OUTPUT_COMPARE_MATCH:
659 #if defined(COMPONENT_CAT1B)
660 return block == 0
661 ? (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_CC_MATCH0 + chnl, CYHAL_SIGNAL_TYPE_EDGE)
662 : (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM1_TR_CC_MATCH0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
663 #else
664 return block == 0
665 ? (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_COMPARE_MATCH0 + chnl, CYHAL_SIGNAL_TYPE_EDGE)
666 : (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM1_TR_COMPARE_MATCH0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
667 #endif
668 default:
669 // Should never reach here
670 CY_ASSERT(false);
671 return CYHAL_TRIGGER_CPUSS_ZERO;
672 }
673 #elif (CY_IP_M0S8TCPWM_VERSION == 2)
674 CY_UNUSED_PARAMETER(block);
675 switch(signal)
676 {
677 case CYHAL_TCPWM_OUTPUT_OVERFLOW:
678 return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM_TR_OVERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
679 case CYHAL_TCPWM_OUTPUT_UNDERFLOW:
680 return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM_TR_UNDERFLOW0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
681 case CYHAL_TCPWM_OUTPUT_COMPARE_MATCH:
682 return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM_TR_COMPARE_MATCH0 + chnl, CYHAL_SIGNAL_TYPE_EDGE);
683 default:
684 // Should never reach here
685 CY_ASSERT(false);
686 return CYHAL_TRIGGER_CPUSS_ZERO;
687 }
688 #endif
689 }
690 #elif (CY_IP_MXTCPWM_VERSION == 2U)
691 static cyhal_source_t _cyhal_tcpwm_calculate_source(uint8_t out_trig_idx, uint8_t free_trig)
692 {
693 // Triggers are ordered by output trig idx, then block, then channel.
694 // Offsetting by out_trig_idx is sufficient to get the correct trigger.
695 if(free_trig == 0)
696 {
697 return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_OUT00 + out_trig_idx, CYHAL_SIGNAL_TYPE_EDGE);
698 }
699 else if(free_trig == 1)
700 {
701 return (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(_CYHAL_TRIGGER_TCPWM0_TR_OUT10 + out_trig_idx, CYHAL_SIGNAL_TYPE_EDGE);
702 }
703 else
704 {
705 // Should never reach here
706 CY_ASSERT(false);
707 return CYHAL_TRIGGER_CPUSS_ZERO;
708 }
709 }
710 #endif
711 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
712
713 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)
714 {
715 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
716 cy_rslt_t rslt = CY_RSLT_SUCCESS;
717 cyhal_signal_type_t signal_type = _CYHAL_TRIGGER_GET_SOURCE_TYPE(source);
718 if((CYHAL_SIGNAL_TYPE_LEVEL == signal_type) != (CYHAL_EDGE_TYPE_LEVEL == type))
719 {
720 rslt = CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
721 }
722
723 const uint8_t block = obj->resource.block_num;
724 uint8_t trig_index = 0;
725
726 if(CY_RSLT_SUCCESS == rslt)
727 {
728 #if defined (COMPONENT_CAT5)
729 // Note: Only applicable for Quaddec on this device. Triggers are hardcoded.
730 switch(signal)
731 {
732 case CYHAL_TCPWM_INPUT_COUNT: /* phiA */
733 trig_index = 0;
734 break;
735 case CYHAL_TCPWM_INPUT_START: /* phiB */
736 trig_index = 1;
737 break;
738 case CYHAL_TCPWM_INPUT_RELOAD: /* index */
739 trig_index = 2;
740 break;
741 default:
742 rslt = CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
743 break;
744 }
745 #else
746 // Find free input trigger index
747 uint32_t saved_intr_status = cyhal_system_critical_section_enter();
748 for(trig_index = 0; trig_index < (_CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[_CYHAL_TCPWM_GET_IP_BLOCK(block)]) ; trig_index++)
749 {
750 cyhal_dest_t dest = _cyhal_tpwm_calculate_dest(block, trig_index);
751
752 /* On some devices, not all triggers connect uniformly to all sources, so make sure the trigger
753 * we're trying to use can actually connect to the source we want to use */
754 rslt = _cyhal_connect_signal(source, dest);
755 if (rslt == CY_RSLT_SUCCESS)
756 {
757 break;
758 }
759 }
760 cyhal_system_critical_section_exit(saved_intr_status);
761
762 if(trig_index == (_CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[_CYHAL_TCPWM_GET_IP_BLOCK(block)]))
763 {
764 rslt = CYHAL_TCPWM_RSLT_ERR_NO_FREE_INPUT_SIGNALS;
765 }
766 #endif
767 }
768
769 if(CY_RSLT_SUCCESS == rslt)
770 {
771 uint16_t trigger_sig = trig_index + _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[_CYHAL_TCPWM_GET_IP_BLOCK(block)];
772 #if (CY_IP_MXTCPWM_VERSION == 1U) || (CY_IP_M0S8TCPWM_VERSION == 2)
773 const uint8_t chnl = obj->resource.channel_num;
774 // Clear appropriate trigger reg field and set input index and edge trigger type
775 // Note: Input trigger indices 0 and 1 are reserved for constant signals 0
776 // and 1 respectively. The first actual trigger input has index 2.
777 switch(signal)
778 {
779 case CYHAL_TCPWM_INPUT_START:
780 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_START_SEL_Msk;
781 TCPWM_CNT_TR_CTRL0(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_START_SEL, trigger_sig);
782 TCPWM_CNT_TR_CTRL1(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL1_START_EDGE_Msk;
783 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_START_EDGE, type);
784 break;
785 case CYHAL_TCPWM_INPUT_STOP:
786 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_STOP_SEL_Msk;
787 TCPWM_CNT_TR_CTRL0(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_STOP_SEL, trigger_sig);
788 TCPWM_CNT_TR_CTRL1(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL1_STOP_EDGE_Msk;
789 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_STOP_EDGE, type);
790 break;
791 case CYHAL_TCPWM_INPUT_RELOAD:
792 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_RELOAD_SEL_Msk;
793 TCPWM_CNT_TR_CTRL0(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_RELOAD_SEL, trigger_sig);
794 TCPWM_CNT_TR_CTRL1(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL1_RELOAD_EDGE_Msk;
795 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_RELOAD_EDGE, type);
796 break;
797 case CYHAL_TCPWM_INPUT_COUNT:
798 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_COUNT_SEL_Msk;
799 TCPWM_CNT_TR_CTRL0(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_COUNT_SEL, trigger_sig);
800 TCPWM_CNT_TR_CTRL1(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL1_COUNT_EDGE_Msk;
801 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_COUNT_EDGE, type);
802 break;
803 case CYHAL_TCPWM_INPUT_CAPTURE:
804 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_CAPTURE_SEL_Msk;
805 TCPWM_CNT_TR_CTRL0(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL0_CAPTURE_SEL, trigger_sig);
806 TCPWM_CNT_TR_CTRL1(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL1_CAPTURE_EDGE_Msk;
807 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_CAPTURE_EDGE, type);
808 break;
809 default:
810 rslt = CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
811 }
812
813 #elif (CY_IP_MXTCPWM_VERSION == 2U)
814 // Clear appropriate trigger reg fields and set input index and edge trigger type.
815 // Note: Cy_TCPWM_InputTriggerSetup assumes channel indices for block 0 are
816 // 0-255 and block 1 are 256-511.
817 uint8_t group = _CYHAL_TCPWM_GET_GRP(block);
818 uint32_t counter = _CYHAL_TCPWM_CNT_NUMBER(obj->resource);
819 switch(signal)
820 {
821 case CYHAL_TCPWM_INPUT_START:
822 TCPWM_GRP_CNT_TR_IN_SEL1(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL1_START_SEL_Msk;
823 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_START_EDGE_Msk;
824 Cy_TCPWM_InputTriggerSetup(obj->base, counter, CY_TCPWM_INPUT_TR_START, type, trigger_sig);
825 break;
826 case CYHAL_TCPWM_INPUT_STOP:
827 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_STOP_SEL_Msk;
828 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_STOP_EDGE_Msk;
829 Cy_TCPWM_InputTriggerSetup(obj->base, counter, CY_TCPWM_INPUT_TR_STOP_OR_KILL, type, trigger_sig);
830 break;
831 case CYHAL_TCPWM_INPUT_RELOAD:
832 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_RELOAD_SEL_Msk;
833 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_RELOAD_EDGE_Msk;
834 Cy_TCPWM_InputTriggerSetup(obj->base, counter, CY_TCPWM_INPUT_TR_RELOAD_OR_INDEX, type, trigger_sig);
835 break;
836 case CYHAL_TCPWM_INPUT_COUNT:
837 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_COUNT_SEL_Msk;
838 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_COUNT_EDGE_Msk;
839 Cy_TCPWM_InputTriggerSetup(obj->base, counter, CY_TCPWM_INPUT_TR_COUNT, type, trigger_sig);
840 break;
841 case CYHAL_TCPWM_INPUT_CAPTURE:
842 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_CAPTURE0_SEL_Msk;
843 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, group, counter) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_CAPTURE0_EDGE_Msk;
844 Cy_TCPWM_InputTriggerSetup(obj->base, counter, CY_TCPWM_INPUT_TR_CAPTURE0, type, trigger_sig);
845 break;
846 default:
847 rslt = CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
848 }
849 #else
850 #error Unrecognized TCPWM version
851 #endif
852 }
853
854 if(CY_RSLT_SUCCESS == rslt)
855 {
856 obj->inputs[(uint32_t)signal] = source;
857 }
858 else if((_CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[_CYHAL_TCPWM_GET_IP_BLOCK(block)]) != trig_index)
859 {
860 /* If we made a connection before erroring out later, undo the connection */
861 cyhal_dest_t dest = _cyhal_tpwm_calculate_dest(block, trig_index);
862 cy_rslt_t disconnect_rslt = _cyhal_disconnect_signal(source, dest);
863 /* Deliberately not impacting the return value, because we're already in an error state. A successful
864 * disconnect won't change that. An unsuccessful disconnect should in theory never happen because if
865 * we got here we made a successful connection above. */
866 CY_ASSERT(CY_RSLT_SUCCESS == disconnect_rslt);
867 CY_UNUSED_PARAMETER(disconnect_rslt); /* Avoid unused variable warning in release builds */
868 }
869
870 return rslt;
871 #else
872 CY_UNUSED_PARAMETER(obj);
873 CY_UNUSED_PARAMETER(source);
874 CY_UNUSED_PARAMETER(signal);
875 CY_UNUSED_PARAMETER(type);
876
877 return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
878 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
879 }
880
881 cy_rslt_t _cyhal_tcpwm_enable_output(cyhal_tcpwm_t *obj, cyhal_tcpwm_output_t signal, cyhal_source_t *source)
882 {
883 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
884 const uint8_t block = obj->resource.block_num;
885 const uint8_t chnl = obj->resource.channel_num;
886
887 // Note that triggers are always generated for TCPWMv1 so this just returns the proper source signal
888 #if (CY_IP_MXTCPWM_VERSION == 1U) || (CY_IP_M0S8TCPWM_VERSION == 2)
889 CY_ASSERT(block < 2);
890
891 *source = _cyhal_tcpwm_calculate_source(block, chnl, signal);
892
893 return CY_RSLT_SUCCESS;
894 #elif (CY_IP_MXTCPWM_VERSION == 2U)
895 uint8_t event_type = _cyhal_tcpwm_convert_output_t(signal);
896
897 // All channels in _CYHAL_OUTPUT_TRIGGERS_USED are just ordered
898 // sequentially, not ordered by blocks.
899 uint8_t out_trig_idx = _CYHAL_TCPWM_GET_ARRAY_INDEX(block, chnl);
900
901 // Find free trigger, if any
902 int8_t free_trig = -1;
903 uint32_t saved_intr_status = cyhal_system_critical_section_enter();
904 if(!(_CYHAL_OUTPUT_TRIGGERS_USED[out_trig_idx] & 1))
905 {
906 // Output trigger idx 0 is free
907 free_trig = 0;
908 _CYHAL_OUTPUT_TRIGGERS_USED[out_trig_idx] |= 1;
909 }
910 else if(!(_CYHAL_OUTPUT_TRIGGERS_USED[out_trig_idx] & 2))
911 {
912 // Output trigger idx 1 is free
913 free_trig = 1;
914 _CYHAL_OUTPUT_TRIGGERS_USED[out_trig_idx] |= 2;
915 }
916 cyhal_system_critical_section_exit(saved_intr_status);
917
918 // Configure trigger out registers
919 if(free_trig == 0)
920 {
921 TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
922 &= ~TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT0_Msk;
923 TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
924 |= _VAL2FLD(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT0, event_type);
925 }
926 else if(free_trig == 1)
927 {
928 TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
929 &= ~TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT1_Msk;
930 TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
931 |= _VAL2FLD(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT1, event_type);
932 }
933 else
934 return CYHAL_TCPWM_RSLT_ERR_NO_FREE_OUTPUT_SIGNALS;
935
936 *source = _cyhal_tcpwm_calculate_source(out_trig_idx, free_trig);
937
938 return CY_RSLT_SUCCESS;
939 #else
940 #error Unrecognized TCPWM version
941 #endif
942 #else
943 CY_UNUSED_PARAMETER(obj);
944 CY_UNUSED_PARAMETER(signal);
945 CY_UNUSED_PARAMETER(source);
946 return CYHAL_TCPWM_RSLT_ERR_NO_FREE_OUTPUT_SIGNALS;
947 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
948 }
949
950 cy_rslt_t _cyhal_tcpwm_disconnect_digital(cyhal_tcpwm_t *obj, cyhal_source_t source, cyhal_tcpwm_input_t signal)
951 {
952 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
953 const uint8_t block = obj->resource.block_num;
954 uint8_t trig_index;
955
956 #if (CY_IP_MXTCPWM_VERSION == 1U) || (CY_IP_M0S8TCPWM_VERSION == 2)
957 const uint8_t chnl = obj->resource.channel_num;
958 switch (signal)
959 {
960 // Grab trig_index then clear/reset to default (CY_TCPWM_INPUT_LEVEL is
961 // default) appropriate ctrl reg fields
962 case CYHAL_TCPWM_INPUT_START:
963 trig_index = _FLD2VAL(TCPWM_CNT_TR_CTRL0_START_SEL, TCPWM_CNT_TR_CTRL0(obj->base, chnl));
964 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_START_SEL_Msk;
965 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_START_EDGE, CY_TCPWM_INPUT_LEVEL);
966 break;
967 case CYHAL_TCPWM_INPUT_STOP:
968 trig_index = _FLD2VAL(TCPWM_CNT_TR_CTRL0_STOP_SEL, TCPWM_CNT_TR_CTRL0(obj->base, chnl));
969 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_STOP_SEL_Msk;
970 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_STOP_EDGE, CY_TCPWM_INPUT_LEVEL);
971 break;
972 case CYHAL_TCPWM_INPUT_RELOAD:
973 trig_index = _FLD2VAL(TCPWM_CNT_TR_CTRL0_RELOAD_SEL, TCPWM_CNT_TR_CTRL0(obj->base, chnl));
974 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_RELOAD_SEL_Msk;
975 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_RELOAD_EDGE, CY_TCPWM_INPUT_LEVEL);
976 break;
977 case CYHAL_TCPWM_INPUT_COUNT:
978 trig_index = _FLD2VAL(TCPWM_CNT_TR_CTRL0_COUNT_SEL, TCPWM_CNT_TR_CTRL0(obj->base, chnl));
979 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_COUNT_SEL_Msk;
980 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_COUNT_EDGE, CY_TCPWM_INPUT_LEVEL);
981 break;
982 case CYHAL_TCPWM_INPUT_CAPTURE:
983 trig_index = _FLD2VAL(TCPWM_CNT_TR_CTRL0_CAPTURE_SEL, TCPWM_CNT_TR_CTRL0(obj->base, chnl));
984 TCPWM_CNT_TR_CTRL0(obj->base, chnl) &= ~TCPWM_CNT_TR_CTRL0_CAPTURE_SEL_Msk;
985 TCPWM_CNT_TR_CTRL1(obj->base, chnl) |= _VAL2FLD(TCPWM_CNT_TR_CTRL1_CAPTURE_EDGE, CY_TCPWM_INPUT_LEVEL);
986 break;
987 default:
988 return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
989 }
990 #elif (CY_IP_MXTCPWM_VERSION == 2U)
991 switch(signal)
992 {
993 case CYHAL_TCPWM_INPUT_START:
994 trig_index = _FLD2VAL(TCPWM_GRP_CNT_V2_TR_IN_SEL1_START_SEL, TCPWM_GRP_CNT_TR_IN_SEL1(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
995 _CYHAL_TCPWM_CNT_NUMBER(obj->resource)));
996 TCPWM_GRP_CNT_TR_IN_SEL1(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL1_START_SEL_Msk;
997 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_START_EDGE_Msk;
998 break;
999 case CYHAL_TCPWM_INPUT_STOP:
1000 trig_index = _FLD2VAL(TCPWM_GRP_CNT_V2_TR_IN_SEL0_STOP_SEL, TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
1001 _CYHAL_TCPWM_CNT_NUMBER(obj->resource)));
1002 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_STOP_SEL_Msk;
1003 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_STOP_EDGE_Msk;
1004 break;
1005 case CYHAL_TCPWM_INPUT_RELOAD:
1006 trig_index = _FLD2VAL(TCPWM_GRP_CNT_V2_TR_IN_SEL0_RELOAD_SEL, TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
1007 _CYHAL_TCPWM_CNT_NUMBER(obj->resource)));
1008 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_RELOAD_SEL_Msk;
1009 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_RELOAD_EDGE_Msk;
1010 break;
1011 case CYHAL_TCPWM_INPUT_COUNT:
1012 trig_index = _FLD2VAL(TCPWM_GRP_CNT_V2_TR_IN_SEL0_COUNT_SEL, TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
1013 _CYHAL_TCPWM_CNT_NUMBER(obj->resource)));
1014 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_COUNT_SEL_Msk;
1015 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_COUNT_EDGE_Msk;
1016 break;
1017 case CYHAL_TCPWM_INPUT_CAPTURE:
1018 trig_index = _FLD2VAL(TCPWM_GRP_CNT_V2_TR_IN_SEL0_CAPTURE0_SEL, TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
1019 _CYHAL_TCPWM_CNT_NUMBER(obj->resource)));
1020 TCPWM_GRP_CNT_TR_IN_SEL0(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_SEL0_CAPTURE0_SEL_Msk;
1021 TCPWM_GRP_CNT_TR_IN_EDGE_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) &= ~TCPWM_GRP_CNT_V2_TR_IN_EDGE_SEL_CAPTURE0_EDGE_Msk;
1022 break;
1023 default:
1024 return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
1025 }
1026 #else
1027 #error Unrecognized TCPWM version
1028 #endif
1029
1030 trig_index -= (_CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[_CYHAL_TCPWM_GET_IP_BLOCK(block)]);
1031
1032 cyhal_dest_t dest = _cyhal_tpwm_calculate_dest(block, trig_index);
1033
1034 cy_rslt_t rslt = _cyhal_disconnect_signal(source, dest);
1035 if (CY_RSLT_SUCCESS == rslt)
1036 {
1037 obj->inputs[(uint32_t)signal] = CYHAL_TRIGGER_CPUSS_ZERO;
1038 }
1039 return rslt;
1040 #else
1041 CY_UNUSED_PARAMETER(obj);
1042 CY_UNUSED_PARAMETER(signal);
1043 CY_UNUSED_PARAMETER(source);
1044 return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
1045 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
1046 }
1047
1048 cy_rslt_t _cyhal_tcpwm_disable_output(cyhal_tcpwm_t *obj, cyhal_tcpwm_output_t signal)
1049 {
1050 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
1051 // Triggers are always generated for TCPWMv1 so this is a noop.
1052 #if (CY_IP_MXTCPWM_VERSION == 1U) || (CY_IP_M0S8TCPWM_VERSION == 2)
1053 CY_UNUSED_PARAMETER(obj);
1054 CY_UNUSED_PARAMETER(signal);
1055
1056 return CY_RSLT_SUCCESS;
1057 #elif (CY_IP_MXTCPWM_VERSION == 2U)
1058 const uint8_t block = obj->resource.block_num;
1059 const uint8_t chnl = obj->resource.channel_num;
1060
1061 uint8_t event_type = _cyhal_tcpwm_convert_output_t(signal);
1062
1063 // All channels in _CYHAL_OUTPUT_TRIGGERS_USED are just ordered
1064 // sequentially, not ordered by blocks.
1065 uint8_t trig_index = _CYHAL_TCPWM_GET_ARRAY_INDEX(block, chnl);
1066
1067 if(_FLD2VAL(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT0, TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
1068 _CYHAL_TCPWM_CNT_NUMBER(obj->resource))) == event_type)
1069 {
1070 // Disable output trigger idx 0
1071 TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
1072 &= ~TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT0_Msk;
1073 TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
1074 |= _VAL2FLD(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT0, CY_TCPWM_CNT_TRIGGER_ON_DISABLED);
1075 _CYHAL_OUTPUT_TRIGGERS_USED[trig_index] &= ~1;
1076 }
1077 else if(_FLD2VAL(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT1, TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), \
1078 _CYHAL_TCPWM_CNT_NUMBER(obj->resource))) == event_type)
1079 {
1080 // Disable output trigger idx 1
1081 TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
1082 &= ~TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT1_Msk;
1083 TCPWM_GRP_CNT_TR_OUT_SEL(obj->base, _CYHAL_TCPWM_GET_GRP(block), _CYHAL_TCPWM_CNT_NUMBER(obj->resource)) \
1084 |= _VAL2FLD(TCPWM_GRP_CNT_V2_TR_OUT_SEL_OUT1, CY_TCPWM_CNT_TRIGGER_ON_DISABLED);
1085 _CYHAL_OUTPUT_TRIGGERS_USED[trig_index] &= ~2;
1086 }
1087 else
1088 return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
1089
1090 return CY_RSLT_SUCCESS;
1091 #else
1092 #error Unrecognized TCPWM version
1093 #endif
1094 #else
1095 CY_UNUSED_PARAMETER(obj);
1096 CY_UNUSED_PARAMETER(signal);
1097
1098 return CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT;
1099 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
1100 }
1101
1102 #if defined(__cplusplus)
1103 }
1104 #endif
1105
1106 #endif /* _CYHAL_DRIVER_AVAILABLE_TCPWM */
1107