1 /***************************************************************************//**
2 * \file cyhal_interconnect.c
3 *
4 * \brief
5 * Provides a high level interface for interacting with the internal digital
6 * routing on the chip. This is a wrapper around the lower level PDL API.
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
11 * an affiliate of Cypress Semiconductor Corporation
12 *
13 * SPDX-License-Identifier: Apache-2.0
14 *
15 * Licensed under the Apache License, Version 2.0 (the "License");
16 * you may not use this file except in compliance with the License.
17 * You may obtain a copy of the License at
18 *
19 * http://www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing, software
22 * distributed under the License is distributed on an "AS IS" BASIS,
23 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 * See the License for the specific language governing permissions and
25 * limitations under the License.
26 *******************************************************************************/
27
28 #include "cyhal_interconnect.h"
29 #include "cyhal_gpio_impl.h"
30
31 #if defined(__cplusplus)
32 extern "C"
33 {
34 #endif
35
36 #if (CYHAL_DRIVER_AVAILABLE_INTERCONNECT)
37
38 typedef enum
39 {
40 CYHAL_CONNECT_TYPE_VALIDATE,
41 CYHAL_CONNECT_TYPE_CONNECT,
42 CYHAL_CONNECT_TYPE_DISCONNECT,
43 } cyhal_connect_type_t;
44
45 // Only define if there are actual trigger signals
46 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
47 //Need to take peri #
48 #ifdef CY_IP_M0S8PERI_INSTANCES
49 #define _CYHAL_PERI_INSTANCES (CY_IP_M0S8PERI_INSTANCES)
50 #elif defined(CY_IP_MXSPERI_INSTANCES)
51 #define _CYHAL_PERI_INSTANCES (CY_IP_MXSPERI_INSTANCES)
52 #elif defined(CY_IP_MXPERI_TR_INSTANCES)
53 #define _CYHAL_PERI_INSTANCES (CY_IP_MXPERI_TR_INSTANCES)
54 #endif
55 #ifdef _CYHAL_PERI_INSTANCES
56 static uint8_t _CYHAL_INTERCONNECT_BASE_IDX[_CYHAL_PERI_INSTANCES] = {
57 0,
58 #if (_CYHAL_PERI_INSTANCES == 2)
59 PERI0_TR_GROUP_NR,
60 #elif (_CYHAL_PERI_INSTANCES > 2)
61 #error "Max amount of PERI instances is 2"
62 //For current devices there is a maximum of 2 PERI instances possible
63 #endif
64 };
65
get_peri_block_from_trigger(uint8_t mux_group)66 static uint32_t get_peri_block_from_trigger(uint8_t mux_group)
67 {
68 uint32_t blk_idx = 0;
69 for(uint8_t i = 0; i < _CYHAL_PERI_INSTANCES;i++)
70 {
71 if(mux_group > _CYHAL_INTERCONNECT_BASE_IDX[i])
72 {
73 blk_idx=i;
74 }
75 }
76 return blk_idx;
77 }
78
get_local_peri_group_num_from_trigger(uint8_t mux_group)79 static uint32_t get_local_peri_group_num_from_trigger(uint8_t mux_group)
80 {
81 return ((uint32_t)(mux_group - _CYHAL_INTERCONNECT_BASE_IDX[get_peri_block_from_trigger(mux_group)]));
82 }
83 // Helpers for creating Cy_TrigMux_* inputs //helper for local peri based group
84 #define CY_TRIGMUX_INPUT_LINE(mux_group, source_idx) (uint32_t)(((get_local_peri_group_num_from_trigger(mux_group))) << 8 | (source_idx) | (get_peri_block_from_trigger(mux_group) << 16u))
85 #define CY_TRIGMUX_OUTPUT_LINE(mux_group, dest_idx) (uint32_t)(0x40000000 | ((get_local_peri_group_num_from_trigger(mux_group))) << 8 | (dest_idx) | (get_peri_block_from_trigger(mux_group) << 16u))
86 #define CY_SELECT_OUTPUT_LINE(mux_group, dest_idx) (uint32_t)(0x40001000 | ((get_local_peri_group_num_from_trigger(mux_group))) << 8 | (dest_idx) | (get_peri_block_from_trigger(mux_group) << 16u))
87 #else
88 #error "No PERI Instances"
89 #endif
90 #if (CY_IP_MXPERI_VERSION >= 2u) || (CY_IP_M0S8PERI_VERSION >= 1u) || (CY_IP_MXSPERI >= 1u)
_cyhal_get_first_1to1_mux_idx(void)91 static int8_t _cyhal_get_first_1to1_mux_idx(void)
92 {
93 for(uint8_t idx = 0; idx < (sizeof(cyhal_is_mux_1to1)/sizeof(cyhal_is_mux_1to1[0])); idx++)
94 {
95 if(cyhal_is_mux_1to1[idx])
96 return idx;
97 }
98
99 return -1;
100 }
101 #endif
102
103 // Reads peri trigmux register and returns the selected input line (0 is
104 // default if no line has been selected)
_cyhal_read_mux_input_idx(uint8_t mux_group,uint8_t mux_output_idx)105 static uint8_t _cyhal_read_mux_input_idx(uint8_t mux_group, uint8_t mux_output_idx)
106 {
107 #if (CY_IP_MXPERI_VERSION >= 2u) || (CY_IP_M0S8PERI_VERSION >= 1u) || (CY_IP_MXSPERI >= 1u)
108 const int8_t MUX_GROUP_1TO1_OFFSET = _cyhal_get_first_1to1_mux_idx();
109 const uint8_t FIRST_1TO1_MUX_GROUP_IDX = 16;
110 #endif
111
112 uint32_t mux_reg = 0;
113 #if (CY_IP_MXPERI_VERSION >= 2u) || (CY_IP_M0S8PERI_VERSION == 1u) || (CY_IP_MXSPERI >= 1u)
114 // M0S8 has no 1to1 muxes but the table is still valid
115 if(cyhal_is_mux_1to1[mux_group])
116 {
117 // There are up to 16 regular mux groups and up to 16 1to1 mux groups
118 // (in PSoC™ 6). PERI_TR_GR_TR_CTL starts at the first regular mux so
119 // offset by 16 if reading a 1to1 mux.
120 mux_reg = PERI_TR_GR_TR_CTL(mux_group - MUX_GROUP_1TO1_OFFSET + FIRST_1TO1_MUX_GROUP_IDX, mux_output_idx);
121 }
122 else
123 {
124 mux_reg = PERI_TR_GR_TR_CTL(mux_group, mux_output_idx);
125 }
126 #else // CY_IP_MXPERI_VERSION == 1
127 mux_reg = PERI_TR_GR_TR_CTL(mux_group, mux_output_idx);
128 #endif
129
130
131 #if (CY_IP_MXPERI_VERSION >= 1u) || (CY_IP_MXSPERI >= 1u)
132 return _FLD2VAL(PERI_TR_GR_TR_OUT_CTL_TR_SEL, mux_reg);
133 #elif CY_IP_M0S8PERI_VERSION == 1u
134 return _FLD2VAL(PERI_TR_CTL_TR_SEL, mux_reg);
135 #endif
136 }
137
138 #if (CY_IP_MXPERI_VERSION >= 2u) || (CY_IP_M0S8PERI_VERSION == 1u) || (CY_IP_MXSPERI >= 1u)
_cyhal_interconnect_change_connection_direct(uint8_t mux_group,uint8_t mux_group_1to1_offset,uint8_t source_idx,uint8_t dest_idx,cyhal_signal_type_t type,bool connect)139 static cy_rslt_t _cyhal_interconnect_change_connection_direct(
140 uint8_t mux_group, uint8_t mux_group_1to1_offset, uint8_t source_idx, uint8_t dest_idx, cyhal_signal_type_t type, bool connect)
141 {
142 #if CY_IP_M0S8PERI_VERSION == 1u
143 CY_UNUSED_PARAMETER(type);
144 CY_UNUSED_PARAMETER(mux_group_1to1_offset);
145 #endif
146
147 if(cyhal_is_mux_1to1[mux_group])
148 {
149 #if (CY_IP_MXPERI_VERSION >= 2u) || (CY_IP_MXSPERI >= 1u)
150 // Cy_TrigMux_Select assumes the mux_group idx param starts from the
151 // first 1to1 mux (so first 1to1 mux is 0)
152 uint32_t out_trig = CY_SELECT_OUTPUT_LINE(mux_group - mux_group_1to1_offset, dest_idx);
153
154 if(connect)
155 return Cy_TrigMux_Select(out_trig, false, (en_trig_type_t)type);
156 else
157 return Cy_TrigMux_Deselect(out_trig);
158 #else
159 return (connect)
160 ? CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION
161 : CYHAL_INTERCONNECT_RSLT_CANNOT_DISCONNECT;
162 #endif
163 }
164 else
165 {
166 uint32_t in_trig = CY_TRIGMUX_INPUT_LINE(mux_group, source_idx);
167 uint32_t out_trig = CY_TRIGMUX_OUTPUT_LINE(mux_group, dest_idx);
168
169 if(connect)
170 {
171 #if (CY_IP_MXPERI_VERSION >= 2u) || (CY_IP_MXSPERI >= 1u)
172 return Cy_TrigMux_Connect(in_trig, out_trig, false, (en_trig_type_t)type);
173 #else
174 return Cy_TrigMux_Connect(in_trig, out_trig);
175 #endif
176 }
177 else
178 {
179 // No Cy_TrigMux_Disconnect so just clear register of found
180 // mux input line.
181 PERI_TR_GR_TR_CTL(mux_group, dest_idx) = 0;
182 return CY_RSLT_SUCCESS;
183 }
184 }
185 }
186 #elif CY_IP_MXPERI_VERSION == 1u
187 /* Change a HAL trigger connection where a mux is involved */
_cyhal_interconnect_change_connection_direct(uint8_t mux,uint8_t input_idx,uint8_t output_idx,cyhal_signal_type_t type,bool connect)188 static cy_rslt_t _cyhal_interconnect_change_connection_direct(uint8_t mux, uint8_t input_idx, uint8_t output_idx, cyhal_signal_type_t type, bool connect)
189 {
190 if (connect)
191 {
192 uint32_t in_trig = CY_TRIGMUX_INPUT_LINE(mux, input_idx);
193 uint32_t out_trig = CY_TRIGMUX_OUTPUT_LINE(mux, output_idx);
194
195 return Cy_TrigMux_Connect(in_trig, out_trig, false, (en_trig_type_t)type);
196 }
197 else
198 {
199 PERI_TR_GR_TR_CTL(mux, output_idx) = 0;
200 return CY_RSLT_SUCCESS;
201 }
202 }
203
204 /* Change a HAL trigger connection where 2 muxes are involved */
_cyhal_interconnect_change_connection_indirect(uint8_t source_mux_group,uint8_t source_mux_input_idx,uint8_t source_mux_output_idx,uint8_t dest_mux_group,uint8_t dest_mux_input_idx,uint8_t dest_mux_output_idx,cyhal_signal_type_t type,bool connect)205 static cy_rslt_t _cyhal_interconnect_change_connection_indirect(uint8_t source_mux_group, uint8_t source_mux_input_idx, uint8_t source_mux_output_idx,
206 uint8_t dest_mux_group, uint8_t dest_mux_input_idx, uint8_t dest_mux_output_idx, cyhal_signal_type_t type, bool connect)
207 {
208 if(connect)
209 {
210 // Construct Cy_TrigMux_Connect trigger inputs for both source and dest muxes
211 uint32_t source_mux_in_trig = CY_TRIGMUX_INPUT_LINE(source_mux_group, source_mux_input_idx);
212 uint32_t source_mux_out_trig = CY_TRIGMUX_OUTPUT_LINE(source_mux_group, source_mux_output_idx);
213
214 uint32_t dest_mux_in_trig = CY_TRIGMUX_INPUT_LINE(dest_mux_group, dest_mux_input_idx);
215 uint32_t dest_mux_out_trig = CY_TRIGMUX_OUTPUT_LINE(dest_mux_group, dest_mux_output_idx);
216
217 if(_cyhal_read_mux_input_idx(dest_mux_group, dest_mux_output_idx) != 0)
218 {
219 return CYHAL_INTERCONNECT_RSLT_ALREADY_CONNECTED;
220 }
221
222 cy_rslt_t result = Cy_TrigMux_Connect(source_mux_in_trig, source_mux_out_trig, false, (en_trig_type_t)type);
223 if (CY_RSLT_SUCCESS == result)
224 result = Cy_TrigMux_Connect(dest_mux_in_trig, dest_mux_out_trig, false, (en_trig_type_t)type);
225 return result;
226 }
227 else
228 {
229 // No Cy_TrigMux_Disconnect so just clear registers of found muxes
230 PERI_TR_GR_TR_CTL(source_mux_group, source_mux_output_idx) = 0;
231 PERI_TR_GR_TR_CTL(dest_mux_group, dest_mux_output_idx) = 0;
232 return CY_RSLT_SUCCESS;
233 }
234 }
235 #endif /* #if CY_IP_MXPERI_VERSION >= 2u || CY_IP_M0S8PERI_VERSION == 1u */
236
237 // Since both connect and disconnect need to derive mux group(s) and trigger
238 // indices, use this func to avoid duplicate code.
_cyhal_interconnect_check_connection(cyhal_source_t source,cyhal_dest_t dest,cyhal_connect_type_t connect)239 static cy_rslt_t _cyhal_interconnect_check_connection(cyhal_source_t source, cyhal_dest_t dest, cyhal_connect_type_t connect)
240 {
241 cyhal_internal_source_t internal_src = _CYHAL_TRIGGER_GET_SOURCE_SIGNAL(source);
242 cyhal_signal_type_t type = _CYHAL_TRIGGER_GET_SOURCE_TYPE(source);
243 #if CY_IP_MXPERI_VERSION >= 2u || CY_IP_M0S8PERI_VERSION >= 1u || CY_IP_MXSPERI >= 1u
244 const int8_t mux_group_1to1_offset = _cyhal_get_first_1to1_mux_idx();
245
246 // cyhal_dest_to_mux stores 1to1 triggers with bit 8 set and the lower 7
247 // bits as the offset into the 1to1 triggers (so 128 is 1to1 mux index 0)
248 // but here we need the actual group offset for all the triggers.
249 uint8_t mux_group = cyhal_dest_to_mux[dest];
250 if(mux_group & 0x80)
251 mux_group = mux_group_1to1_offset + (mux_group & ~0x80);
252 // Ensure mux_group is within the range of cyhal_mux_to_sources to avoid
253 // out-of-bounds indexing
254 if (mux_group >= (sizeof(cyhal_mux_to_sources) / sizeof(cyhal_mux_to_sources[0])))
255 {
256 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
257 }
258
259 uint8_t dest_idx = cyhal_mux_dest_index[dest];
260
261 // Search through table of mux input trigger lines
262 for (uint16_t source_idx = 0; source_idx < cyhal_sources_per_mux[mux_group]; source_idx++)
263 {
264 if(cyhal_mux_to_sources[mux_group][source_idx] == internal_src)
265 {
266 // 1to1 triggers muxes source and dest indices must match
267 if(cyhal_is_mux_1to1[mux_group] && (source_idx != dest_idx))
268 {
269 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
270 }
271
272 // Check if the mux is already configured (possibly from a
273 // different source)
274 if(CYHAL_CONNECT_TYPE_DISCONNECT != connect
275 && _cyhal_read_mux_input_idx(mux_group, dest_idx) != 0)
276 {
277 return CYHAL_INTERCONNECT_RSLT_ALREADY_CONNECTED;
278 }
279
280 return (connect == CYHAL_CONNECT_TYPE_VALIDATE)
281 ? CY_RSLT_SUCCESS
282 : _cyhal_interconnect_change_connection_direct(mux_group, mux_group_1to1_offset, source_idx, dest_idx, type, connect == CYHAL_CONNECT_TYPE_CONNECT);
283 }
284 }
285 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
286 #elif CY_IP_MXPERI_VERSION == 1u
287 uint8_t dest_mux_group = cyhal_dest_to_mux[dest];
288 uint8_t dest_mux_output_idx = cyhal_mux_dest_index[dest];
289
290 // Special case 1: DW sources connect to USB_DMA_BURSTEND destinations directly
291 // through mux 9 so handle here.
292 if(dest_mux_group == 9)
293 {
294 if((internal_src < _CYHAL_TRIGGER_CPUSS_DW0_TR_OUT0) || (internal_src > _CYHAL_TRIGGER_CPUSS_DW1_TR_OUT15))
295 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
296
297 if((dest < CYHAL_TRIGGER_USB_DMA_BURSTEND0) || (dest > CYHAL_TRIGGER_USB_DMA_BURSTEND7))
298 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
299
300 uint16_t mux9_input_idx = (uint16_t)(internal_src - _CYHAL_TRIGGER_CPUSS_DW0_TR_OUT0) + 1;
301 uint16_t mux9_output_idx = (uint16_t)(dest - CYHAL_TRIGGER_USB_DMA_BURSTEND0);
302
303 uint8_t set_input_idx = _cyhal_read_mux_input_idx(9, mux9_output_idx);
304 if ((CYHAL_CONNECT_TYPE_DISCONNECT != connect) && (set_input_idx != 0))
305 return CYHAL_INTERCONNECT_RSLT_ALREADY_CONNECTED;
306 else if ((CYHAL_CONNECT_TYPE_DISCONNECT == connect) && (set_input_idx == 0))
307 return CYHAL_INTERCONNECT_RSLT_CANNOT_DISCONNECT;
308 else
309 {
310 return (connect == CYHAL_CONNECT_TYPE_VALIDATE)
311 ? CY_RSLT_SUCCESS
312 : _cyhal_interconnect_change_connection_direct(9, mux9_input_idx, mux9_output_idx, type, connect == CYHAL_CONNECT_TYPE_CONNECT);
313 }
314 }
315
316 // Special case 2: UDB_TR_DW_ACK destinations have no destinations side mux
317 // and are instead only connected through mux 10. Handle those connections
318 // here (while handling all other connections through mux 10 later).
319 if((dest_mux_group == 10) && (dest >= CYHAL_TRIGGER_UDB_TR_DW_ACK0) && (dest <= CYHAL_TRIGGER_UDB_TR_DW_ACK7))
320 {
321 if((internal_src < _CYHAL_TRIGGER_CPUSS_DW0_TR_OUT0) || (internal_src > _CYHAL_TRIGGER_CPUSS_DW1_TR_OUT15))
322 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
323
324 uint16_t mux10_input_idx = (uint16_t)(internal_src - _CYHAL_TRIGGER_CPUSS_DW0_TR_OUT0) + 1;
325 uint16_t mux10_output_idx = (uint16_t)(dest - CYHAL_TRIGGER_UDB_TR_DW_ACK0);
326
327 uint8_t set_input_idx = _cyhal_read_mux_input_idx(10, mux10_output_idx);
328 if ((CYHAL_CONNECT_TYPE_DISCONNECT != connect) && (set_input_idx != 0))
329 return CYHAL_INTERCONNECT_RSLT_ALREADY_CONNECTED;
330 else if ((CYHAL_CONNECT_TYPE_DISCONNECT == connect) && (set_input_idx == 0))
331 return CYHAL_INTERCONNECT_RSLT_CANNOT_DISCONNECT;
332 else
333 {
334 return (connect == CYHAL_CONNECT_TYPE_VALIDATE)
335 ? CY_RSLT_SUCCESS
336 : _cyhal_interconnect_change_connection_direct(10, mux10_input_idx, mux10_output_idx, type, connect == CYHAL_CONNECT_TYPE_CONNECT);
337 }
338 }
339
340 // Since PSoC™ 6 BLE devices w/ trigmux vers1 have a 1to1 relationship
341 // between peripheral sources and reduction trigger muxes (besides DW which
342 // connects to trig mux 9 and 10, handled above) it is possible to search
343 // through source mux tables to find the idx required.
344 uint16_t source_mux_group = 0;
345 uint16_t source_mux_input_idx = 0;
346 bool found_source_mux_info = false;
347 for(source_mux_group = 10; source_mux_group < 15; source_mux_group++)
348 {
349 for(source_mux_input_idx = 0; source_mux_input_idx < cyhal_sources_per_mux[source_mux_group]; source_mux_input_idx++)
350 {
351 if(cyhal_mux_to_sources[source_mux_group][source_mux_input_idx] == internal_src)
352 {
353 found_source_mux_info = true;
354 break;
355 }
356 }
357 if(found_source_mux_info)
358 break;
359 }
360
361 if(!found_source_mux_info)
362 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
363
364 // Construct the cyhal_internal_source_t range that contains all possible inputs
365 // from the source mux to the dest mux. Not every cyhal_internal_source_t in this
366 // range will go to the dest mux but dest_mux_input_line_low and
367 // dest_mux_input_line_high will be used in the next step to find which inputs can.
368 cyhal_internal_source_t dest_mux_input_line_low;
369 cyhal_internal_source_t dest_mux_input_line_high;
370 switch (source_mux_group)
371 {
372 case 10:
373 dest_mux_input_line_low = _CYHAL_TRIGGER_TR_GROUP10_OUTPUT0;
374 dest_mux_input_line_high = _CYHAL_TRIGGER_TR_GROUP10_OUTPUT7;
375 break;
376 case 11:
377 dest_mux_input_line_low = _CYHAL_TRIGGER_TR_GROUP11_OUTPUT0;
378 dest_mux_input_line_high = _CYHAL_TRIGGER_TR_GROUP11_OUTPUT15;
379 break;
380 case 12:
381 dest_mux_input_line_low = _CYHAL_TRIGGER_TR_GROUP12_OUTPUT0;
382 dest_mux_input_line_high = _CYHAL_TRIGGER_TR_GROUP12_OUTPUT9;
383 break;
384 case 13:
385 dest_mux_input_line_low = _CYHAL_TRIGGER_TR_GROUP13_OUTPUT0;
386 dest_mux_input_line_high = _CYHAL_TRIGGER_TR_GROUP13_OUTPUT17;
387 break;
388 case 14:
389 dest_mux_input_line_low = _CYHAL_TRIGGER_TR_GROUP14_OUTPUT0;
390 dest_mux_input_line_high = _CYHAL_TRIGGER_TR_GROUP14_OUTPUT15;
391 break;
392 default:
393 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
394 }
395
396 // Search through the dest mux source table to find the low and high
397 // indices of the valid inputs from the source mux to the dest mux. These
398 // indices will correspond to, and be between, dest_mux_input_line_low and
399 // dest_mux_input_line_high (but not necessarily the whole range). If e.g
400 // only source mux output lines 8-9 go to the dest mux this will be
401 // reflected by setting source_mux_start_idx to 8
402 uint16_t dest_mux_input_line_low_idx = 10000;
403 uint16_t dest_mux_input_line_high_idx = 0;
404 uint16_t source_mux_start_idx = 0;
405 for(uint16_t i = 0; i < cyhal_sources_per_mux[dest_mux_group]; i++)
406 {
407 if((cyhal_mux_to_sources[dest_mux_group][i] >= dest_mux_input_line_low) &&
408 (cyhal_mux_to_sources[dest_mux_group][i] <= dest_mux_input_line_high))
409 {
410 if(dest_mux_input_line_low_idx > i)
411 {
412 dest_mux_input_line_low_idx = i;
413 source_mux_start_idx = (uint16_t)(cyhal_mux_to_sources[dest_mux_group][i] - dest_mux_input_line_low);
414 }
415
416 if(dest_mux_input_line_high_idx < i)
417 dest_mux_input_line_high_idx = i;
418 }
419 }
420
421 // Construct possible output trigger lines from the source mux starting at
422 // the first input line found in the previous step. Since source mux output
423 // lines can be arbitrarily selected and may already be in use, read the
424 // source mux register to check if an output is free.
425 uint8_t source_mux_output_idx = 0;
426 uint8_t dest_mux_input_idx = 0;
427 bool found_connection = false;
428 for(source_mux_output_idx = source_mux_start_idx; source_mux_output_idx < (source_mux_start_idx + (dest_mux_input_line_high_idx - dest_mux_input_line_low_idx + 1)); source_mux_output_idx++)
429 {
430 // If connecting: Check if possible output trigger is free.
431 if((connect != CYHAL_CONNECT_TYPE_DISCONNECT) && _cyhal_read_mux_input_idx(source_mux_group, source_mux_output_idx) == 0)
432 {
433 dest_mux_input_idx = dest_mux_input_line_low_idx + source_mux_output_idx - source_mux_start_idx;
434
435 found_connection = true;
436 break;
437 }
438 // If disconnecting: We have already used this source mux output line
439 // and it matches the inputted source. Since disconnecting only
440 // requires output idx info (for both muxes) nothing needs to be
441 // calculated here.
442 else if((connect == CYHAL_CONNECT_TYPE_DISCONNECT) && _cyhal_read_mux_input_idx(source_mux_group, source_mux_output_idx) == source_mux_input_idx)
443 {
444 found_connection = true;
445 break;
446 }
447 }
448
449 if(!found_connection)
450 {
451 return (connect == CYHAL_CONNECT_TYPE_DISCONNECT)
452 ? CYHAL_INTERCONNECT_RSLT_CANNOT_DISCONNECT
453 : CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
454 }
455
456 return (connect == CYHAL_CONNECT_TYPE_VALIDATE)
457 ? CY_RSLT_SUCCESS
458 : _cyhal_interconnect_change_connection_indirect(source_mux_group, source_mux_input_idx, source_mux_output_idx,
459 dest_mux_group, dest_mux_input_idx, dest_mux_output_idx, type, connect == CYHAL_CONNECT_TYPE_CONNECT);
460 #else
461 #error Unrecognized PERI version
462 #endif
463 }
464
465 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
466
_cyhal_connect_signal(cyhal_source_t source,cyhal_dest_t dest)467 cy_rslt_t _cyhal_connect_signal(cyhal_source_t source, cyhal_dest_t dest)
468 {
469 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
470 return _cyhal_interconnect_check_connection(source, dest, CYHAL_CONNECT_TYPE_CONNECT);
471 #else
472 CY_UNUSED_PARAMETER(source);
473 CY_UNUSED_PARAMETER(dest);
474 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
475 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
476 }
477
_cyhal_disconnect_signal(cyhal_source_t source,cyhal_dest_t dest)478 cy_rslt_t _cyhal_disconnect_signal(cyhal_source_t source, cyhal_dest_t dest)
479 {
480 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
481 return _cyhal_interconnect_check_connection(source, dest, CYHAL_CONNECT_TYPE_DISCONNECT);
482 #else
483 CY_UNUSED_PARAMETER(source);
484 CY_UNUSED_PARAMETER(dest);
485 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
486 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
487 }
488
_cyhal_can_connect_signal(cyhal_source_t source,cyhal_dest_t dest)489 bool _cyhal_can_connect_signal(cyhal_source_t source, cyhal_dest_t dest)
490 {
491 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
492 return (CY_RSLT_SUCCESS == _cyhal_interconnect_check_connection(source, dest, CYHAL_CONNECT_TYPE_VALIDATE));
493 #else
494 CY_UNUSED_PARAMETER(source);
495 CY_UNUSED_PARAMETER(dest);
496 return false;
497 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
498 }
499
500 #endif /* CYHAL_DRIVER_AVAILABLE_INTERCONNECT */
501
cyhal_connect_pin(const cyhal_resource_pin_mapping_t * pin_connection,uint8_t drive_mode)502 cy_rslt_t cyhal_connect_pin(const cyhal_resource_pin_mapping_t *pin_connection, uint8_t drive_mode)
503 {
504 cyhal_gpio_t pin = pin_connection->pin;
505 GPIO_PRT_Type *port = Cy_GPIO_PortToAddr(CYHAL_GET_PORT(pin));
506 en_hsiom_sel_t hsiom = pin_connection->hsiom;
507
508 Cy_GPIO_Pin_FastInit(port, CYHAL_GET_PIN(pin), drive_mode, 1, hsiom);
509 // Force output to enable pulls.
510 switch (drive_mode)
511 {
512 case CY_GPIO_DM_PULLUP:
513 Cy_GPIO_Write(port, CYHAL_GET_PIN(pin), 1);
514 break;
515 case CY_GPIO_DM_PULLDOWN:
516 Cy_GPIO_Write(port, CYHAL_GET_PIN(pin), 0);
517 break;
518 default:
519 /* do nothing */
520 break;
521 }
522
523 return CY_RSLT_SUCCESS;
524 }
525
cyhal_disconnect_pin(cyhal_gpio_t pin)526 cy_rslt_t cyhal_disconnect_pin(cyhal_gpio_t pin)
527 {
528 GPIO_PRT_Type *port = Cy_GPIO_PortToAddr(CYHAL_GET_PORT(pin));
529
530 Cy_GPIO_Pin_FastInit(port, CYHAL_GET_PIN(pin), CY_GPIO_DM_HIGHZ, 1, HSIOM_SEL_GPIO);
531
532 return CY_RSLT_SUCCESS;
533 }
534
535 #if defined(__cplusplus)
536 }
537 #endif
538