1 /***************************************************************************//**
2 * \file cy_trigmux.c
3 * \version 1.30
4 *
5 * \brief Trigger mux API.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2016-2020 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 *     http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24 
25 #include "cy_device.h"
26 
27 #if defined (CY_IP_MXSPERI) || defined (CY_IP_MXPERI)
28 
29 #include "cy_trigmux.h"
30 
31 #define CY_TRIGMUX_IS_TRIGTYPE_VALID(trigType)  (((trigType) == TRIGGER_TYPE_EDGE) || \
32                                                  ((trigType) == TRIGGER_TYPE_LEVEL))
33 
34 #define CY_TRIGMUX_V1_IS_CYCLES_VALID(cycles)   (CY_TRIGGER_INFINITE >= (cycles))
35 #define CY_TRIGMUX_V2_IS_CYCLES_VALID(cycles)   ((CY_TRIGGER_DEACTIVATE == (cycles)) || \
36                                                  (CY_TRIGGER_TWO_CYCLES == (cycles)) || \
37                                                  (CY_TRIGGER_INFINITE   == (cycles)))
38 #define CY_TRIGMUX_IS_CYCLES_VALID(cycles)      ((CY_PERI_V1 && CY_TRIGMUX_V1_IS_CYCLES_VALID(cycles)) || \
39                                                                 CY_TRIGMUX_V2_IS_CYCLES_VALID(cycles))
40 
41 #define CY_TRIGMUX_INTRIG_MASK                  (PERI_TR_CMD_GROUP_SEL_Msk | PERI_TR_GR_TR_OUT_CTL_TR_SEL_Msk)
42 #define CY_TRIGMUX_IS_INTRIG_VALID(inTrg)       (0UL == ((inTrg) & (uint32_t)~CY_TRIGMUX_INTRIG_MASK))
43 
44 #define CY_TRIGMUX_OUTTRIG_MASK                 (PERI_TR_CMD_OUT_SEL_Msk | PERI_TR_CMD_GROUP_SEL_Msk | CY_PERI_TR_CTL_SEL_Msk)
45 #define CY_TRIGMUX_IS_OUTTRIG_VALID(outTrg)     ((0UL == ((outTrg) & (uint32_t)~CY_TRIGMUX_OUTTRIG_MASK)) && \
46                                                  (0UL != ((outTrg) & PERI_TR_CMD_OUT_SEL_Msk)))
47 
48 #define CY_TRIGMUX_ONETRIG_MASK                 (PERI_V2_TR_CMD_OUT_SEL_Msk | PERI_V2_TR_CMD_GROUP_SEL_Msk | CY_PERI_TR_CTL_SEL_Msk)
49 
50 #if defined (CY_IP_MXSPERI)
51 #define CY_TRIGMUX_ONETRIG_GR_START                0x10UL /* trigger 1-1 group [16-31] */
52 #define CY_TRIGMUX_IS_ONETRIG_VALID(oneTrg)     ((0UL == ((oneTrg) & (uint32_t)~CY_TRIGMUX_ONETRIG_MASK)) && \
53                                                  (0UL != ((oneTrg) & PERI_V2_TR_CMD_OUT_SEL_Msk)) && \
54                                                  (0UL != (_FLD2VAL(PERI_V2_TR_CMD_GROUP_SEL, oneTrg) & (uint32_t)CY_TRIGMUX_ONETRIG_GR_START)))
55 #else
56 #define CY_TRIGMUX_IS_ONETRIG_VALID(oneTrg)     ((0UL == ((oneTrg) & (uint32_t)~CY_TRIGMUX_ONETRIG_MASK)) && \
57                                                  (0UL != ((oneTrg) & PERI_V2_TR_CMD_OUT_SEL_Msk)) && \
58                                                  (0UL != ((oneTrg) & (PERI_V2_TR_CMD_GROUP_SEL_Msk & (uint32_t)~PERI_TR_CMD_GROUP_SEL_Msk))))
59 #endif
60 
61 #define CY_TRIGMUX_TRIGLINE_MASK                (PERI_TR_CMD_OUT_SEL_Msk | CY_PERI_TR_CMD_GROUP_SEL_Msk | CY_PERI_TR_CTL_SEL_Msk)
62 #define CY_TRIGMUX_IS_TRIGLINE_VALID(trgLn)     (0U == ((trgLn) & (uint32_t)~CY_TRIGMUX_TRIGLINE_MASK))
63 
64 #define CY_TRIGMUX_TR_CTL(outTrig)              (PERI_TR_GR_TR_CTL(_FLD2VAL(CY_PERI_TR_CMD_GROUP_SEL, outTrig), \
65                                                                    _FLD2VAL(CY_PERI_TR_CTL_SEL,       outTrig)))
66 
67 
68 /*******************************************************************************
69 * Function Name: Cy_TrigMux_Connect
70 ****************************************************************************//**
71 *
72 * Connects an input trigger source and output trigger.
73 *
74 * \param inTrig
75 * An input selection for the trigger mux.
76 * - Bit 30 should be cleared.
77 * - Bit 12 should be cleared.
78 * - Bits 11:8 represent the trigger group selection.
79 * - Bits 7:0 select the input trigger signal for the specified trigger multiplexer.
80 *
81 * \param outTrig
82 * The output of the trigger mux. This refers to the consumer of the trigger mux.
83 * - Bit 30 should be set.
84 * - Bit 12 should be cleared.
85 * - Bits 11:8 represent the trigger group selection.<br>
86 *  For PERI_ver1:
87 * - Bits 6:0 select the output trigger number in the trigger group.<br>
88 *  For PERI_ver2:
89 * - Bits 7:0 select the output trigger number in the trigger group.
90 *
91 * \param invert
92 * - true: The output trigger is inverted.
93 * - false: The output trigger is not inverted.
94 *
95 * \param trigType The trigger signal type.
96 * - TRIGGER_TYPE_EDGE: The trigger is synchronized to the consumer blocks clock
97 *   and a two-cycle pulse is generated on this clock.
98 * - TRIGGER_TYPE_LEVEL: The trigger is a simple level output.
99 *
100 * \return status:
101 * - CY_TRIGMUX_SUCCESS: The connection is made successfully.
102 * - CY_TRIGMUX_BAD_PARAM: Some parameter is invalid.
103 *
104 * \funcusage
105 * \snippet trigmux/snippet/main.c snippet_Cy_TrigMux_Connect
106 *
107 *******************************************************************************/
Cy_TrigMux_Connect(uint32_t inTrig,uint32_t outTrig,bool invert,en_trig_type_t trigType)108 cy_en_trigmux_status_t Cy_TrigMux_Connect(uint32_t inTrig, uint32_t outTrig, bool invert, en_trig_type_t trigType)
109 {
110     cy_en_trigmux_status_t retVal = CY_TRIGMUX_BAD_PARAM;
111     CY_ASSERT_L3(CY_TRIGMUX_IS_TRIGTYPE_VALID(trigType));
112     CY_ASSERT_L2(CY_TRIGMUX_IS_INTRIG_VALID(inTrig));
113     CY_ASSERT_L2(CY_TRIGMUX_IS_OUTTRIG_VALID(outTrig));
114 
115     /* inTrig and outTrig should be in the same group */
116     if ((inTrig & PERI_TR_CMD_GROUP_SEL_Msk) == (outTrig & PERI_TR_CMD_GROUP_SEL_Msk))
117     {
118         uint32_t interruptState = Cy_SysLib_EnterCriticalSection();
119 
120         CY_TRIGMUX_TR_CTL(outTrig) = (CY_TRIGMUX_TR_CTL(outTrig) &
121                                       (uint32_t)~(PERI_TR_GR_TR_OUT_CTL_TR_SEL_Msk |
122                                                   PERI_TR_GR_TR_OUT_CTL_TR_INV_Msk |
123                                                   PERI_TR_GR_TR_OUT_CTL_TR_EDGE_Msk)) |
124                                         (_VAL2FLD(PERI_TR_GR_TR_OUT_CTL_TR_SEL, inTrig) |
125                                         _BOOL2FLD(PERI_TR_GR_TR_OUT_CTL_TR_INV, invert) |
126                                          _VAL2FLD(PERI_TR_GR_TR_OUT_CTL_TR_EDGE, trigType));
127 
128         Cy_SysLib_ExitCriticalSection(interruptState);
129 
130         retVal = CY_TRIGMUX_SUCCESS;
131     }
132 
133     return retVal;
134 }
135 
136 
137 /*******************************************************************************
138 * Function Name: Cy_TrigMux_Select
139 ****************************************************************************//**
140 *
141 * Enables and configures the specified 1-to-1 trigger line. For PERI_ver2 only.
142 *
143 * \param outTrig
144 * The 1to1 trigger line.
145 * - Bit 30 should be set.
146 * - Bit 12 should be set.
147 * - Bits 11:8 represent the 1-to-1 trigger group selection.
148 * - Bits 7:0 select the trigger line number in the trigger group.
149 *
150 * \param invert
151 * - true: The trigger signal is inverted.
152 * - false: The trigger signal is not inverted.
153 *
154 * \param trigType The trigger signal type.
155 * - TRIGGER_TYPE_EDGE: The trigger is synchronized to the consumer blocks clock
156 *   and a two-cycle pulse is generated on this clock.
157 * - TRIGGER_TYPE_LEVEL: The trigger is a simple level output.
158 *
159 * \return status:
160 * - CY_TRIGMUX_SUCCESS: The selection is made successfully.
161 * - CY_TRIGMUX_BAD_PARAM: Some parameter is invalid.
162 *
163 * \funcusage
164 * \snippet trigmux/snippet/main.c snippet_Cy_TrigMux_Select
165 *
166 *******************************************************************************/
Cy_TrigMux_Select(uint32_t outTrig,bool invert,en_trig_type_t trigType)167 cy_en_trigmux_status_t Cy_TrigMux_Select(uint32_t outTrig, bool invert, en_trig_type_t trigType)
168 {
169     cy_en_trigmux_status_t retVal = CY_TRIGMUX_BAD_PARAM;
170 
171     CY_ASSERT_L3(CY_TRIGMUX_IS_TRIGTYPE_VALID(trigType));
172     CY_ASSERT_L2(CY_TRIGMUX_IS_ONETRIG_VALID(outTrig));
173 
174     if (!CY_PERI_V1)
175     {
176         uint32_t interruptState;
177 
178         interruptState = Cy_SysLib_EnterCriticalSection();
179 
180         CY_TRIGMUX_TR_CTL(outTrig) = (CY_TRIGMUX_TR_CTL(outTrig) &
181                           (uint32_t)~(PERI_TR_1TO1_GR_V2_TR_CTL_TR_INV_Msk |
182                                       PERI_TR_1TO1_GR_V2_TR_CTL_TR_EDGE_Msk)) |
183                                      (PERI_TR_1TO1_GR_V2_TR_CTL_TR_SEL_Msk      |
184                             _BOOL2FLD(PERI_TR_1TO1_GR_V2_TR_CTL_TR_INV, invert) |
185                              _VAL2FLD(PERI_TR_1TO1_GR_V2_TR_CTL_TR_EDGE, trigType));
186 
187         Cy_SysLib_ExitCriticalSection(interruptState);
188 
189         retVal = CY_TRIGMUX_SUCCESS;
190     }
191 
192     return retVal;
193 }
194 
195 
196 /*******************************************************************************
197 * Function Name: Cy_TrigMux_Deselect
198 ****************************************************************************//**
199 *
200 * Disables the specified 1-to-1 trigger line. For PERI_ver2 only.
201 *
202 * \param outTrig
203 * The 1to1 trigger line.
204 * - Bit 30 should be set.
205 * - Bit 12 should be set.
206 * - Bits 11:8 represent the 1-to-1 trigger group selection.
207 * - Bits 7:0 select the trigger line number in the trigger group.
208 *
209 * \return status:
210 * - CY_TRIGMUX_SUCCESS: The deselection is made successfully.
211 * - CY_TRIGMUX_BAD_PARAM: Some parameter is invalid.
212 *
213 * \funcusage
214 * \snippet trigmux/snippet/main.c snippet_Cy_TrigMux_Deselect
215 *
216 *******************************************************************************/
Cy_TrigMux_Deselect(uint32_t outTrig)217 cy_en_trigmux_status_t Cy_TrigMux_Deselect(uint32_t outTrig)
218 {
219     cy_en_trigmux_status_t retVal = CY_TRIGMUX_BAD_PARAM;
220 
221     CY_ASSERT_L2(CY_TRIGMUX_IS_ONETRIG_VALID(outTrig));
222 
223     if (!CY_PERI_V1)
224     {
225         uint32_t interruptState;
226 
227         interruptState = Cy_SysLib_EnterCriticalSection();
228 
229         CY_TRIGMUX_TR_CTL(outTrig) &= (uint32_t)~(PERI_TR_1TO1_GR_V2_TR_CTL_TR_SEL_Msk |
230                                                   PERI_TR_1TO1_GR_V2_TR_CTL_TR_INV_Msk |
231                                                   PERI_TR_1TO1_GR_V2_TR_CTL_TR_EDGE_Msk);
232 
233         Cy_SysLib_ExitCriticalSection(interruptState);
234 
235         retVal = CY_TRIGMUX_SUCCESS;
236     }
237 
238     return retVal;
239 }
240 
241 
242 /*******************************************************************************
243 * Function Name: Cy_TrigMux_SetDebugFreeze
244 ****************************************************************************//**
245 *
246 * Enables/disables the Debug Freeze feature for the specified trigger
247 * multiplexer or 1-to-1 trigger line. For PERI_ver2 only.
248 *
249 * \param outTrig
250 * The output of the trigger mux or dedicated 1-to-1 trigger line.
251 * - Bit 30 should be set.
252 * - For PERI_ver1 Bits 11:8 represent the trigger group selection.
253 * - For PERI_ver2 Bits 12:8 represent the trigger group selection.
254 * - Bits 7:0 select the output trigger number in the trigger group.
255 *
256 * \param enable
257 * - true: The Debug Freeze feature is enabled.
258 * - false: The Debug Freeze feature is disabled.
259 *
260 * \return status:
261 * - CY_TRIGMUX_SUCCESS: The operation is made successfully.
262 * - CY_TRIGMUX_BAD_PARAM: The outTrig parameter is invalid.
263 *
264 * \funcusage
265 * \snippet trigmux/snippet/main.c snippet_Cy_TrigMux_SetDebugFreeze
266 *
267 *******************************************************************************/
Cy_TrigMux_SetDebugFreeze(uint32_t outTrig,bool enable)268 cy_en_trigmux_status_t Cy_TrigMux_SetDebugFreeze(uint32_t outTrig, bool enable)
269 {
270     cy_en_trigmux_status_t retVal = CY_TRIGMUX_BAD_PARAM;
271 
272     if (!CY_PERI_V1)
273     {
274         uint32_t interruptState;
275 
276         interruptState = Cy_SysLib_EnterCriticalSection();
277 
278         if (enable)
279         {
280             CY_TRIGMUX_TR_CTL(outTrig) |= PERI_TR_GR_V2_TR_CTL_DBG_FREEZE_EN_Msk;
281         }
282         else
283         {
284             CY_TRIGMUX_TR_CTL(outTrig) &= (uint32_t)~PERI_TR_GR_V2_TR_CTL_DBG_FREEZE_EN_Msk;
285         }
286 
287         Cy_SysLib_ExitCriticalSection(interruptState);
288 
289         retVal = CY_TRIGMUX_SUCCESS;
290     }
291 
292     return retVal;
293 }
294 
295 
296 /*******************************************************************************
297 * Function Name: Cy_TrigMux_SwTrigger
298 ****************************************************************************//**
299 *
300 * This function generates a software trigger on an input trigger line.
301 * All output triggers connected to this input trigger will be triggered.
302 * The function also verifies that there is no activated trigger before
303 * generating another activation.
304 *
305 * \param trigLine
306 * The input of the trigger mux.
307 * - Bit 30 represents if the signal is an input/output. When this bit is set,
308 *   the trigger activation is for an output trigger from the trigger multiplexer.
309 *   When this bit is reset, the trigger activation is for an input trigger to
310 *   the trigger multiplexer.<br>
311 * - For PERI_ver1 Bits 11:8 represent the trigger group selection.<br>
312 * - For PERI_ver2 Bits 12:8 represent the trigger group selection.<br>
313 * In case of output trigger line (bit 30 is set):<br>
314 * For PERI_ver1:
315 * - Bits 6:0 select the output trigger number in the trigger group.<br>
316 * For PERI_ver2:
317 * - Bits 7:0 select the output trigger number in the trigger group.<br>
318 * In case of input trigger line (bit 30 is unset):
319 * - Bits 7:0 select the input trigger signal for the trigger multiplexer.
320 *
321 * \param cycles
322 *  The number of "Clk_Peri" cycles during which the trigger remains activated.<br>
323 *  For PERI_ver1: The valid range of cycles is 1 ... 254.<br>
324 *  For PERI_ver2: The only valid value of cycles is 2 (\ref CY_TRIGGER_TWO_CYCLES).<br>
325 *  Also there are special values (supported with both PERI_ver1 and PERI_ver2):
326 *   - CY_TRIGGER_INFINITE - trigger remains activated until the user deactivates it by
327 *   calling this function with CY_TRIGGER_DEACTIVATE parameter.
328 *   - CY_TRIGGER_DEACTIVATE - this is used to deactivate the trigger activated by
329 *   calling this function with CY_TRIGGER_INFINITE parameter.
330 *
331 * \return status:
332 * - CY_TRIGMUX_SUCCESS: The trigger is successfully activated/deactivated.
333 * - CY_TRIGMUX_INVALID_STATE: The trigger is already activated/not active.
334 * - CY_TRIGMUX_BAD_PARAM: Some parameter is invalid.
335 *
336 * \funcusage
337 * \snippet trigmux/snippet/main.c snippet_Cy_TrigMux_SwTrigger
338 *
339 *******************************************************************************/
Cy_TrigMux_SwTrigger(uint32_t trigLine,uint32_t cycles)340 cy_en_trigmux_status_t Cy_TrigMux_SwTrigger(uint32_t trigLine, uint32_t cycles)
341 {
342     cy_en_trigmux_status_t retVal = CY_TRIGMUX_INVALID_STATE;
343 
344     CY_ASSERT_L2(CY_TRIGMUX_IS_TRIGLINE_VALID(trigLine));
345     CY_ASSERT_L2(CY_TRIGMUX_IS_CYCLES_VALID(cycles));
346 
347     if (CY_TRIGGER_DEACTIVATE != cycles)
348     {
349         /* Activate the trigger if it is not in the active state. */
350         if (PERI_TR_CMD_ACTIVATE_Msk != (PERI_TR_CMD & PERI_TR_CMD_ACTIVATE_Msk))
351         {
352 
353             uint32_t trCmd = (trigLine & (PERI_TR_CMD_TR_SEL_Msk |
354                                           PERI_TR_CMD_OUT_SEL_Msk |
355                                        CY_PERI_TR_CMD_GROUP_SEL_Msk)) |
356                                           PERI_TR_CMD_ACTIVATE_Msk;
357 
358             retVal = CY_TRIGMUX_SUCCESS;
359 
360             if (CY_PERI_V1) /* mxperi_v1 */
361             {
362                 PERI_TR_CMD = trCmd | _VAL2FLD(PERI_TR_CMD_COUNT, cycles);
363             }
364             else if (CY_TRIGGER_TWO_CYCLES == cycles) /* mxperi_v2 or later, 2 cycles pulse */
365             {
366                 PERI_TR_CMD = trCmd | PERI_V2_TR_CMD_TR_EDGE_Msk;
367             }
368             else if (CY_TRIGGER_INFINITE == cycles) /* mxperi_v2 or later, infinite activating */
369             {
370                 PERI_TR_CMD = trCmd;
371             }
372             else /* mxperi_v2 or later, invalid cycles value */
373             {
374                 retVal = CY_TRIGMUX_BAD_PARAM;
375             }
376         }
377     }
378     else
379     {
380         /* Forcibly deactivate the trigger if it is in the active state. */
381         if (PERI_TR_CMD_ACTIVATE_Msk == (PERI_TR_CMD & PERI_TR_CMD_ACTIVATE_Msk))
382         {
383             PERI_TR_CMD = 0UL;
384 
385             retVal = CY_TRIGMUX_SUCCESS;
386         }
387     }
388 
389     return retVal;
390 }
391 
392 #endif /* CY_IP_MXSPERI, CY_IP_MXPERI */
393 
394 /* [] END OF FILE */
395