1 /******************************************************************************
\r
3 * Copyright 2013 Altera Corporation. All Rights Reserved.
\r
5 * Redistribution and use in source and binary forms, with or without
\r
6 * modification, are permitted provided that the following conditions are met:
\r
8 * 1. Redistributions of source code must retain the above copyright notice,
\r
9 * this list of conditions and the following disclaimer.
\r
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
\r
12 * this list of conditions and the following disclaimer in the documentation
\r
13 * and/or other materials provided with the distribution.
\r
15 * 3. The name of the author may not be used to endorse or promote products
\r
16 * derived from this software without specific prior written permission.
\r
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR
\r
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO
\r
21 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
\r
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
\r
23 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
\r
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
\r
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
\r
26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
\r
29 ******************************************************************************/
\r
33 #include <stdbool.h>
\r
35 #include "socal/hps.h"
\r
36 #include "socal/socal.h"
\r
37 #include "socal/alt_gpio.h"
\r
38 #include "socal/alt_rstmgr.h"
\r
40 #include "alt_generalpurpose_io.h"
\r
43 /****************************************************************************************/
\r
44 /******************************* Useful local definitions *******************************/
\r
45 /****************************************************************************************/
\r
47 #define ALT_GPIO_EOPA ALT_GPIO_1BIT_28
\r
48 #define ALT_GPIO_EOPB ALT_GPIO_1BIT_57
\r
49 #define ALT_GPIO_EOPC ALT_HLGPI_15
\r
50 #define ALT_GPIO_BITMASK 0x1FFFFFFF
\r
52 // expands the zero or one bit to the 29-bit GPIO word
\r
53 #define ALT_GPIO_ALLORNONE(tst) ((uint32_t) ((tst == 0) ? 0 : ALT_GPIO_BITMASK))
\r
56 /****************************************************************************************/
\r
57 /* alt_gpio_init() initializes the GPIO modules */
\r
58 /****************************************************************************************/
\r
60 ALT_STATUS_CODE alt_gpio_init(void)
\r
62 // put GPIO modules into system manager reset if not already there
\r
64 // release GPIO modules from system reset (w/ two-instruction delay)
\r
65 alt_replbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_GPIO0_SET_MSK |
\r
66 ALT_RSTMGR_PERMODRST_GPIO1_SET_MSK |
\r
67 ALT_RSTMGR_PERMODRST_GPIO2_SET_MSK, 0);
\r
68 return ALT_E_SUCCESS;
\r
72 /****************************************************************************************/
\r
73 /* alt_gpio_uninit() uninitializes the GPIO modules */
\r
74 /****************************************************************************************/
\r
76 ALT_STATUS_CODE alt_gpio_uninit(void)
\r
78 // put all GPIO modules into system manager reset
\r
79 alt_replbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_GPIO0_SET_MSK |
\r
80 ALT_RSTMGR_PERMODRST_GPIO1_SET_MSK |
\r
81 ALT_RSTMGR_PERMODRST_GPIO2_SET_MSK,
\r
83 return ALT_E_SUCCESS;
\r
87 /****************************************************************************************/
\r
88 /* alt_gpio_port_datadir_set() sets the specified GPIO data bits to use the data */
\r
89 /* direction(s) specified. 0 = input (default). 1 = output. */
\r
90 /****************************************************************************************/
\r
92 ALT_STATUS_CODE alt_gpio_port_datadir_set(ALT_GPIO_PORT_t gpio_pid,
\r
93 uint32_t mask, uint32_t config)
\r
95 volatile uint32_t *addr;
\r
97 if ((mask & ~ALT_GPIO_BITMASK) || (config & ~ALT_GPIO_BITMASK)) { return ALT_E_ERROR; }
\r
98 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_SWPORTA_DDR_ADDR; }
\r
99 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_SWPORTA_DDR_ADDR; }
\r
100 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_SWPORTA_DDR_ADDR; }
\r
101 else { return ALT_E_BAD_ARG; }
\r
103 alt_replbits_word(addr, mask, config);
\r
104 return ALT_E_SUCCESS;
\r
108 /****************************************************************************************/
\r
109 /* alt_gpio_port_datadir_get() returns the data direction configuration of selected */
\r
110 /* bits of the designated GPIO module. */
\r
111 /****************************************************************************************/
\r
113 uint32_t alt_gpio_port_datadir_get(ALT_GPIO_PORT_t gpio_pid,
\r
116 volatile uint32_t *addr;
\r
118 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_SWPORTA_DDR_ADDR; }
\r
119 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_SWPORTA_DDR_ADDR; }
\r
120 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_SWPORTA_DDR_ADDR; }
\r
123 return alt_read_word(addr) & mask;
\r
127 /****************************************************************************************/
\r
128 /* alt_gpio_port_data_write() sets the GPIO data outputs of the specified GPIO module */
\r
129 /* to a one or zero. Actual outputs are only set if the data direction for that bit(s) */
\r
130 /* has previously been set to configure them as output(s). */
\r
131 /****************************************************************************************/
\r
133 ALT_STATUS_CODE alt_gpio_port_data_write(ALT_GPIO_PORT_t gpio_pid,
\r
134 uint32_t mask, uint32_t val)
\r
136 volatile uint32_t *addr;
\r
138 if ((mask & ~ALT_GPIO_BITMASK) || (val & ~ALT_GPIO_BITMASK)) { return ALT_E_ERROR; }
\r
139 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_SWPORTA_DR_ADDR; }
\r
140 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_SWPORTA_DR_ADDR; }
\r
141 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_SWPORTA_DR_ADDR; }
\r
142 else { return ALT_E_BAD_ARG; }
\r
144 alt_replbits_word(addr, mask, val);
\r
145 return ALT_E_SUCCESS;
\r
149 /****************************************************************************************/
\r
150 /* alt_gpio_port_data_read() returns the value of the data inputs of the specified */
\r
151 /* GPIO module. Data direction for these bits must have been previously set to inputs. */
\r
152 /****************************************************************************************/
\r
154 #if (!ALT_GPIO_DATAREAD_TEST_MODE)
\r
155 /* This is the production code version. For software unit testing, set the */
\r
156 /* ALT_GPIO_DATAREAD_TEST_MODE flag to true in the makefile, which will compile */
\r
157 /* the GPIO test software version of alt_gpio_port_data_read() instead. */
\r
159 uint32_t alt_gpio_port_data_read(ALT_GPIO_PORT_t gpio_pid, uint32_t mask)
\r
161 volatile uint32_t *addr;
\r
163 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_EXT_PORTA_ADDR; }
\r
164 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_EXT_PORTA_ADDR; }
\r
165 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_EXT_PORTA_ADDR; }
\r
168 return alt_read_word(addr) & mask;
\r
173 /****************************************************************************************/
\r
174 /* alt_gpio_port_int_type_set() sets selected signals of the specified GPIO port to */
\r
175 /* be either level-sensitive ( =0) or edge-triggered ( =1). */
\r
176 /****************************************************************************************/
\r
178 ALT_STATUS_CODE alt_gpio_port_int_type_set(ALT_GPIO_PORT_t gpio_pid,
\r
179 uint32_t mask, uint32_t config)
\r
181 volatile uint32_t *addr;
\r
183 if ((mask & ~ALT_GPIO_BITMASK) || (config & ~ALT_GPIO_BITMASK)) { return ALT_E_ERROR; }
\r
184 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTTYPE_LEVEL_ADDR; }
\r
185 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTTYPE_LEVEL_ADDR; }
\r
186 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTTYPE_LEVEL_ADDR; }
\r
187 else { return ALT_E_BAD_ARG; }
\r
189 alt_replbits_word(addr, mask, config);
\r
190 return ALT_E_SUCCESS;
\r
194 /****************************************************************************************/
\r
195 /* alt_gpio_port_int_type_get() returns the interrupt configuration (edge-triggered or */
\r
196 /* level-triggered) for the specified signals of the specified GPIO module. */
\r
197 /****************************************************************************************/
\r
199 uint32_t alt_gpio_port_int_type_get(ALT_GPIO_PORT_t gpio_pid,
\r
202 volatile uint32_t *addr;
\r
204 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTTYPE_LEVEL_ADDR; }
\r
205 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTTYPE_LEVEL_ADDR; }
\r
206 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTTYPE_LEVEL_ADDR; }
\r
209 return alt_read_word(addr) & mask;
\r
213 /****************************************************************************************/
\r
214 /* alt_gpio_port_int_pol_set() sets the interrupt polarity of the signals of the */
\r
215 /* specified GPIO register (when used as inputs) to active-high ( =0) or active-low */
\r
217 /****************************************************************************************/
\r
219 ALT_STATUS_CODE alt_gpio_port_int_pol_set(ALT_GPIO_PORT_t gpio_pid,
\r
220 uint32_t mask, uint32_t config)
\r
222 volatile uint32_t *addr;
\r
224 if ((mask & ~ALT_GPIO_BITMASK) || (config & ~ALT_GPIO_BITMASK)) { return ALT_E_ERROR; }
\r
225 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INT_POL_ADDR; }
\r
226 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INT_POL_ADDR; }
\r
227 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INT_POL_ADDR; }
\r
228 else { return ALT_E_BAD_ARG; }
\r
230 alt_replbits_word(addr, mask, config);
\r
231 return ALT_E_SUCCESS;
\r
235 /****************************************************************************************/
\r
236 /* alt_gpio_port_int_pol_get() returns the active-high or active-low polarity */
\r
237 /* configuration for the possible interrupt sources of the specified GPIO module. */
\r
238 /* 0 = The interrupt polarity for this bit is set to active-low mode. 1 = The */
\r
239 /* interrupt polarity for this bit is set to active-highmode. */
\r
240 /****************************************************************************************/
\r
242 uint32_t alt_gpio_port_int_pol_get(ALT_GPIO_PORT_t gpio_pid,
\r
245 volatile uint32_t *addr;
\r
247 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INT_POL_ADDR; }
\r
248 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INT_POL_ADDR; }
\r
249 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INT_POL_ADDR; }
\r
252 return alt_read_word(addr) & mask;
\r
256 /****************************************************************************************/
\r
257 /* alt_gpio_port_debounce_set() sets the debounce configuration for input signals of */
\r
258 /* the specified GPIO module. 0 - Debounce is not selected for this signal (default). */
\r
259 /* 1 - Debounce is selected for this signal. */
\r
260 /****************************************************************************************/
\r
262 ALT_STATUS_CODE alt_gpio_port_debounce_set(ALT_GPIO_PORT_t gpio_pid,
\r
263 uint32_t mask, uint32_t config)
\r
265 volatile uint32_t *addr;
\r
267 if ((mask & ~ALT_GPIO_BITMASK) || (config & ~ALT_GPIO_BITMASK)) { return ALT_E_ERROR; }
\r
268 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_DEBOUNCE_ADDR; }
\r
269 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_DEBOUNCE_ADDR; }
\r
270 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_DEBOUNCE_ADDR; }
\r
271 else { return ALT_E_BAD_ARG; }
\r
273 alt_replbits_word(addr, mask, config);
\r
274 return ALT_E_SUCCESS;
\r
278 /****************************************************************************************/
\r
279 /* alt_gpio_port_debounce_get() returns the debounce configuration for the input */
\r
280 /* signals of the specified GPIO register. 0 - Debounce is not selected for this */
\r
281 /* signal. 1 - Debounce is selected for this signal. */
\r
282 /****************************************************************************************/
\r
284 uint32_t alt_gpio_port_debounce_get(ALT_GPIO_PORT_t gpio_pid,
\r
287 volatile uint32_t *addr;
\r
289 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_DEBOUNCE_ADDR; }
\r
290 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_DEBOUNCE_ADDR; }
\r
291 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_DEBOUNCE_ADDR; }
\r
294 return alt_read_word(addr) & mask;
\r
298 /****************************************************************************************/
\r
299 /* alt_gpio_port_sync_set() sets the synchronization configuration for the signals of */
\r
300 /* the specified GPIO register. This allows for synchronizing level-sensitive */
\r
301 /* interrupts to the internal clock signal. This is a port-wide option that controls */
\r
302 /* all level-sensitive interrupt signals of that GPIO port. */
\r
303 /****************************************************************************************/
\r
305 ALT_STATUS_CODE alt_gpio_port_sync_set(ALT_GPIO_PORT_t gpio_pid, uint32_t config)
\r
307 volatile uint32_t *addr;
\r
309 config = (config != 0) ? 1 : 0;
\r
310 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_LS_SYNC_ADDR; }
\r
311 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_LS_SYNC_ADDR; }
\r
312 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_LS_SYNC_ADDR; }
\r
313 else { return ALT_E_BAD_ARG; }
\r
315 alt_write_word(addr, config);
\r
316 return ALT_E_SUCCESS;
\r
320 /****************************************************************************************/
\r
321 /* alt_gpio_port_sync_get() returns the synchronization configuration for the signals */
\r
322 /* of the specified GPIO register. This allows for synchronizing level-sensitive */
\r
323 /* interrupts to the internal clock signal. This is a port-wide option that controls */
\r
324 /* all level-sensitive interrupt signals of that GPIO port. */
\r
325 /****************************************************************************************/
\r
327 ALT_STATUS_CODE alt_gpio_port_sync_get(ALT_GPIO_PORT_t gpio_pid)
\r
329 volatile uint32_t *addr;
\r
331 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_LS_SYNC_ADDR; }
\r
332 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_LS_SYNC_ADDR; }
\r
333 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_LS_SYNC_ADDR; }
\r
334 else { return ALT_E_BAD_ARG; } // error
\r
336 return (alt_read_word(addr) != 0) ? ALT_E_TRUE : ALT_E_FALSE;
\r
340 /****************************************************************************************/
\r
341 /* alt_gpio_port_config() configures a group of GPIO signals with the same parameters. */
\r
342 /* Allows for configuring all parameters of a given port at one time. */
\r
343 /****************************************************************************************/
\r
345 ALT_STATUS_CODE alt_gpio_port_config(ALT_GPIO_PORT_t gpio_pid,
\r
346 uint32_t mask, ALT_GPIO_PIN_DIR_t dir, ALT_GPIO_PIN_TYPE_t type,
\r
347 ALT_GPIO_PIN_POL_t pol, ALT_GPIO_PIN_DEBOUNCE_t debounc,
\r
350 ALT_STATUS_CODE ret;
\r
352 // set all affected GPIO bits to inputs
\r
353 ret = alt_gpio_port_datadir_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(ALT_GPIO_PIN_INPUT));
\r
354 // the ALT_GPIO_ALLORNONE() macro expands the zero or one bit to the 29-bit GPIO word
\r
356 // set trigger type
\r
357 if (ret == ALT_E_SUCCESS)
\r
359 ret = alt_gpio_port_int_type_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(type));
\r
363 if (ret == ALT_E_SUCCESS)
\r
365 alt_gpio_port_int_pol_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(pol));
\r
369 if (ret == ALT_E_SUCCESS)
\r
371 alt_gpio_port_debounce_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(debounc));
\r
374 // set data output(s)
\r
375 if (ret == ALT_E_SUCCESS)
\r
377 alt_gpio_port_data_write(gpio_pid, mask, ALT_GPIO_ALLORNONE(data));
\r
380 if (ret == ALT_E_SUCCESS)
\r
382 // set data direction of one or more bits to select output
\r
383 ret = alt_gpio_port_datadir_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(dir));
\r
390 /****************************************************************************************/
\r
391 /* Enables the specified GPIO data register interrupts. */
\r
392 /****************************************************************************************/
\r
394 ALT_STATUS_CODE alt_gpio_port_int_enable(ALT_GPIO_PORT_t gpio_pid, uint32_t config)
\r
396 volatile uint32_t *addr;
\r
398 if (config & ~ALT_GPIO_BITMASK) { return ALT_E_ERROR; }
\r
399 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTEN_ADDR; }
\r
400 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTEN_ADDR; }
\r
401 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTEN_ADDR; }
\r
402 else { return ALT_E_BAD_ARG; }
\r
404 alt_replbits_word(addr, config, UINT32_MAX);
\r
405 return ALT_E_SUCCESS;
\r
409 /****************************************************************************************/
\r
410 /* Disables the specified GPIO data module interrupts. */
\r
411 /****************************************************************************************/
\r
413 ALT_STATUS_CODE alt_gpio_port_int_disable(ALT_GPIO_PORT_t gpio_pid, uint32_t config)
\r
415 volatile uint32_t *addr;
\r
417 if (config & ~ALT_GPIO_BITMASK) { return ALT_E_ERROR; }
\r
418 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTEN_ADDR; }
\r
419 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTEN_ADDR; }
\r
420 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTEN_ADDR; }
\r
421 else { return ALT_E_BAD_ARG; }
\r
423 alt_replbits_word(addr, config, 0);
\r
424 return ALT_E_SUCCESS;
\r
429 /****************************************************************************************/
\r
430 /* Get the current state of the specified GPIO port interrupts enables. */
\r
431 /****************************************************************************************/
\r
433 uint32_t alt_gpio_port_int_enable_get(ALT_GPIO_PORT_t gpio_pid)
\r
435 volatile uint32_t *addr;
\r
437 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTEN_ADDR; }
\r
438 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTEN_ADDR; }
\r
439 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTEN_ADDR; }
\r
442 return alt_read_word(addr);
\r
446 /****************************************************************************************/
\r
447 /* Masks or unmasks selected interrupt source bits of the data register of the */
\r
448 /* specified GPIO module. Uses a second bit mask to determine which signals may be */
\r
449 /* changed by this call. */
\r
450 /****************************************************************************************/
\r
452 ALT_STATUS_CODE alt_gpio_port_int_mask_set(ALT_GPIO_PORT_t gpio_pid,
\r
453 uint32_t mask, uint32_t val)
\r
455 volatile uint32_t *addr;
\r
457 if ((mask & ~ALT_GPIO_BITMASK) || (val & ~ALT_GPIO_BITMASK)) { return ALT_E_ERROR; }
\r
458 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTMSK_ADDR; }
\r
459 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTMSK_ADDR; }
\r
460 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTMSK_ADDR; }
\r
461 else { return ALT_E_BAD_ARG; } // argument error
\r
463 alt_replbits_word(addr, mask, val);
\r
464 return ALT_E_SUCCESS;
\r
468 /****************************************************************************************/
\r
469 /* Returns the interrupt source mask of the specified GPIO module. */
\r
470 /****************************************************************************************/
\r
472 uint32_t alt_gpio_port_int_mask_get(ALT_GPIO_PORT_t gpio_pid)
\r
474 volatile uint32_t *addr;
\r
476 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTMSK_ADDR; }
\r
477 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTMSK_ADDR; }
\r
478 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTMSK_ADDR; }
\r
479 else { return 0; } // error
\r
481 return alt_read_word(addr);
\r
485 /****************************************************************************************/
\r
486 /* alt_gpio_port_int_status_get() returns the interrupt pending status of all signals */
\r
487 /* of the specified GPIO register. */
\r
488 /****************************************************************************************/
\r
490 uint32_t alt_gpio_port_int_status_get(ALT_GPIO_PORT_t gpio_pid)
\r
492 volatile uint32_t *addr;
\r
494 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTSTAT_ADDR; }
\r
495 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTSTAT_ADDR; }
\r
496 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTSTAT_ADDR; }
\r
497 else { return 0; } // error
\r
499 return alt_read_word(addr);
\r
503 /****************************************************************************************/
\r
504 /* Clear the interrupt pending status of selected signals of the specified GPIO */
\r
506 /****************************************************************************************/
\r
508 ALT_STATUS_CODE alt_gpio_port_int_status_clear(ALT_GPIO_PORT_t gpio_pid,
\r
511 volatile uint32_t *addr;
\r
513 if (clrmask & ~ALT_GPIO_BITMASK) { return ALT_E_ERROR; }
\r
514 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTSTAT_ADDR; }
\r
515 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTSTAT_ADDR; }
\r
516 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTSTAT_ADDR; }
\r
517 else { return ALT_E_BAD_ARG; } // argument error
\r
519 alt_write_word(addr, clrmask);
\r
520 return ALT_E_SUCCESS;
\r
524 /****************************************************************************************/
\r
525 /* alt_gpio_port_idcode_get() returns the ID code of the specified GPIO module. */
\r
526 /****************************************************************************************/
\r
528 uint32_t alt_gpio_port_idcode_get(ALT_GPIO_PORT_t gpio_pid)
\r
530 volatile uint32_t *addr;
\r
532 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_ID_CODE_ADDR; }
\r
533 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_ID_CODE_ADDR; }
\r
534 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_ID_CODE_ADDR; }
\r
537 return alt_read_word(addr);
\r
541 /****************************************************************************************/
\r
542 /* alt_gpio_port_ver_get() returns the version code of the specified GPIO module. */
\r
543 /****************************************************************************************/
\r
545 uint32_t alt_gpio_port_ver_get(ALT_GPIO_PORT_t gpio_pid)
\r
547 volatile uint32_t *addr;
\r
549 if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_VER_ID_CODE_ADDR; }
\r
550 else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_VER_ID_CODE_ADDR; }
\r
551 else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_VER_ID_CODE_ADDR; }
\r
554 return alt_read_word(addr);
\r
558 /****************************************************************************************/
\r
559 /* alt_gpio_bit_config() configures one bit (signal) of the GPIO ports. */
\r
560 /****************************************************************************************/
\r
562 ALT_STATUS_CODE alt_gpio_bit_config(ALT_GPIO_1BIT_t signal_num,
\r
563 ALT_GPIO_PIN_DIR_t dir, ALT_GPIO_PIN_TYPE_t type,
\r
564 ALT_GPIO_PIN_POL_t pol, ALT_GPIO_PIN_DEBOUNCE_t debounce,
\r
565 ALT_GPIO_PIN_DATA_t data)
\r
567 ALT_GPIO_PORT_t pid;
\r
570 pid = alt_gpio_bit_to_pid(signal_num);
\r
571 mask = 0x1 << alt_gpio_bit_to_port_pin(signal_num);
\r
572 return alt_gpio_port_config(pid, mask, dir, type, pol, debounce, data);
\r
576 /****************************************************************************************/
\r
577 /* Returns the configuration parameters of a given GPIO bit. */
\r
578 /****************************************************************************************/
\r
580 ALT_STATUS_CODE alt_gpio_bitconfig_get(ALT_GPIO_1BIT_t signal_num,
\r
581 ALT_GPIO_CONFIG_RECORD_t *config)
\r
583 ALT_STATUS_CODE ret = ALT_E_ERROR;
\r
584 ALT_GPIO_PORT_t pid;
\r
585 uint32_t mask, shift;
\r
587 if ((config != NULL) && (signal_num != ALT_END_OF_GPIO_SIGNALS) && (signal_num <= ALT_LAST_VALID_GPIO_BIT))
\r
589 pid = alt_gpio_bit_to_pid(signal_num);
\r
590 shift = alt_gpio_bit_to_port_pin(signal_num);
\r
591 if ((pid != ALT_GPIO_PORT_UNKNOWN) && (shift <= ALT_GPIO_BIT_MAX))
\r
593 config->signal_number = signal_num;
\r
594 mask = 0x00000001 << shift;
\r
595 config->direction = (alt_gpio_port_datadir_get(pid, mask) == 0) ? ALT_GPIO_PIN_INPUT : ALT_GPIO_PIN_OUTPUT;
\r
596 config->type = (alt_gpio_port_int_type_get(pid, mask) == 0) ? ALT_GPIO_PIN_LEVEL_TRIG_INT : ALT_GPIO_PIN_EDGE_TRIG_INT;
\r
598 // save the following data whatever the state of config->direction
\r
599 config->polarity = (alt_gpio_port_int_pol_get(pid, mask) == 0) ? ALT_GPIO_PIN_ACTIVE_LOW : ALT_GPIO_PIN_ACTIVE_HIGH;
\r
600 config->debounce = (alt_gpio_port_debounce_get(pid, mask) == 0) ? ALT_GPIO_PIN_NODEBOUNCE : ALT_GPIO_PIN_DEBOUNCE;
\r
601 config->data = (alt_gpio_port_data_read(pid, mask) == 0) ? ALT_GPIO_PIN_DATAZERO : ALT_GPIO_PIN_DATAONE;
\r
602 ret = ALT_E_SUCCESS;
\r
609 /****************************************************************************************/
\r
610 /* alt_gpio_group_config() configures a list of GPIO bits. The GPIO bits do not have */
\r
611 /* to be configured the same, as was the case for the mask version of this function, */
\r
612 /* alt_gpio_port_config(). Each bit may be configured differently and bits may be */
\r
613 /* listed in any order. */
\r
614 /****************************************************************************************/
\r
616 ALT_STATUS_CODE alt_gpio_group_config(ALT_GPIO_CONFIG_RECORD_t* config_array, uint32_t len)
\r
618 ALT_STATUS_CODE ret = ALT_E_ERROR;
\r
620 if (config_array != NULL)
\r
622 if (config_array->signal_number == ALT_END_OF_GPIO_SIGNALS) { ret = ALT_E_SUCCESS; }
\r
623 // catches the condition where the pointers are good, but the
\r
624 // first index is the escape character - which isn't an error
\r
627 for (; (len-- > 0) && (config_array->signal_number != ALT_END_OF_GPIO_SIGNALS) && (config_array != NULL); config_array++)
\r
629 ret = alt_gpio_bit_config(config_array->signal_number,
\r
630 config_array->direction, config_array->type, config_array->polarity,
\r
631 config_array->debounce, config_array->data);
\r
632 if ((config_array->direction == ALT_GPIO_PIN_OUTPUT) && (ret == ALT_E_SUCCESS))
\r
634 // if the pin is set to be an output, set it to the correct value
\r
635 alt_gpio_port_data_write(alt_gpio_bit_to_pid(config_array->signal_number),
\r
636 0x1 << alt_gpio_bit_to_port_pin(config_array->signal_number),
\r
637 ALT_GPIO_ALLORNONE(config_array->data));
\r
638 // ret should retain the value returned by alt_gpio_bit_config() above
\r
639 // and should not be changed by the alt_gpio_port_data_write() call.
\r
641 if (((ret != ALT_E_SUCCESS) && (config_array->signal_number <= ALT_LAST_VALID_GPIO_BIT))
\r
642 || ((ret == ALT_E_SUCCESS) && (config_array->signal_number > ALT_LAST_VALID_GPIO_BIT)))
\r
654 /****************************************************************************************/
\r
655 /* Returns a list of the pin signal indices and the associated configuration settings */
\r
656 /* (data direction, interrupt type, polarity, debounce, and synchronization) of that */
\r
657 /* list of signals. Only the signal indices in the first field of each configuration */
\r
658 /* record need be filled in. This function will fill in all the other fields of the */
\r
659 /* configuration record, returning all configuration parameters in the array. A signal */
\r
660 /* number index in the array equal to ALT_END_OF_GPIO_SIGNALS (-1) also terminates the */
\r
662 /****************************************************************************************/
\r
664 ALT_STATUS_CODE alt_gpio_group_config_get(ALT_GPIO_CONFIG_RECORD_t *config_array,
\r
667 ALT_STATUS_CODE ret = ALT_E_ERROR;
\r
669 if ((config_array != NULL) && (config_array->signal_number == ALT_END_OF_GPIO_SIGNALS))
\r
671 ret = ALT_E_SUCCESS;
\r
675 for ( ; (len > 0) && (config_array != NULL) && (config_array->signal_number != ALT_END_OF_GPIO_SIGNALS)
\r
676 && (config_array->signal_number <= ALT_LAST_VALID_GPIO_BIT); len--)
\r
678 ret = alt_gpio_bitconfig_get(config_array->signal_number, config_array);
\r
680 if (ret != ALT_E_SUCCESS) { break; }
\r
686 /****************************************************************************************/
\r
687 /* Another way to return a configuration list. The difference between this version and */
\r
688 /* alt_gpio_group_config_get() is that this version follows a separate list of signal */
\r
689 /* indices instead of having the signal list provided in the first field of the */
\r
690 /* configuration records in the array. This function will fill in the fields of the */
\r
691 /* configuration record, returning all configuration parameters in the array. A signal */
\r
692 /* number index in the array equal to ALT_END_OF_GPIO_SIGNALS (-1) also terminates */
\r
694 /****************************************************************************************/
\r
696 ALT_STATUS_CODE alt_gpio_group_config_get2(ALT_GPIO_1BIT_t* pinid_array,
\r
697 ALT_GPIO_CONFIG_RECORD_t *config_array, uint32_t len)
\r
699 ALT_STATUS_CODE ret = ALT_E_ERROR;
\r
701 if ((config_array != NULL) && (pinid_array != NULL) && (*pinid_array == ALT_END_OF_GPIO_SIGNALS))
\r
703 ret = ALT_E_SUCCESS;
\r
704 // catches the condition where the pointers are good, but the
\r
705 // first index is the escape character - which isn't an error
\r
709 for ( ;(len > 0) && (pinid_array != NULL) && (*pinid_array != ALT_END_OF_GPIO_SIGNALS) && (config_array != NULL); len--)
\r
711 ret = alt_gpio_bitconfig_get(*pinid_array, config_array);
\r
714 if (ret != ALT_E_SUCCESS) { break; }
\r
721 /****************************************************************************************/
\r
722 /* A useful utility function. Extracts the GPIO port ID from the supplied GPIO Signal */
\r
723 /* Index Number. */
\r
724 /****************************************************************************************/
\r
726 ALT_GPIO_PORT_t alt_gpio_bit_to_pid(ALT_GPIO_1BIT_t pin_num)
\r
728 ALT_GPIO_PORT_t pid = ALT_GPIO_PORT_UNKNOWN;
\r
730 if (pin_num <= ALT_GPIO_EOPA) { pid = ALT_GPIO_PORTA; }
\r
731 else if (pin_num <= ALT_GPIO_EOPB) { pid = ALT_GPIO_PORTB; }
\r
732 else if (pin_num <= ALT_GPIO_EOPC) { pid = ALT_GPIO_PORTC; }
\r
737 /****************************************************************************************/
\r
738 /* A useful utility function. Extracts the GPIO signal (pin) mask from the supplied */
\r
739 /* GPIO Signal Index Number. */
\r
740 /****************************************************************************************/
\r
742 ALT_GPIO_PORTBIT_t alt_gpio_bit_to_port_pin(ALT_GPIO_1BIT_t pin_num)
\r
744 if (pin_num <= ALT_GPIO_EOPA) {}
\r
745 else if (pin_num <= ALT_GPIO_EOPB) { pin_num -= (ALT_GPIO_EOPA + 1); }
\r
746 else if (pin_num <= ALT_GPIO_EOPC) { pin_num -= (ALT_GPIO_EOPB + 1); }
\r
747 else { return ALT_END_OF_GPIO_PORT_SIGNALS; }
\r
748 return (ALT_GPIO_PORTBIT_t) pin_num;
\r
752 /****************************************************************************************/
\r
753 /* A useful utility function. Extracts the GPIO Signal Index Number from the supplied */
\r
754 /* GPIO port ID and signal mask. If passed a bitmask composed of more than one signal, */
\r
755 /* the signal number of the lowest bitmask presented is returned. */
\r
756 /****************************************************************************************/
\r
758 ALT_GPIO_1BIT_t alt_gpio_port_pin_to_bit(ALT_GPIO_PORT_t pid,
\r
763 for (i=0; i <= ALT_GPIO_BITNUM_MAX ;i++)
\r
765 if (bitmask & 0x00000001)
\r
767 if (pid == ALT_GPIO_PORTA) {}
\r
768 else if (pid == ALT_GPIO_PORTB) { i += ALT_GPIO_EOPA + 1; }
\r
769 else if (pid == ALT_GPIO_PORTC) { i += ALT_GPIO_EOPB + 1; }
\r
770 else { return ALT_END_OF_GPIO_SIGNALS; }
\r
771 return (ALT_GPIO_1BIT_t) i;
\r
775 return ALT_END_OF_GPIO_SIGNALS;
\r