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