]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A9_Cyclone_V_SoC_DK/Altera_Code/HardwareLibrary/alt_generalpurpose_io.c
Update version number in readiness for V10.3.0 release. Sync SVN with reviewed releas...
[freertos] / FreeRTOS / Demo / CORTEX_A9_Cyclone_V_SoC_DK / Altera_Code / HardwareLibrary / alt_generalpurpose_io.c
1 /******************************************************************************\r
2 *\r
3 * Copyright 2013 Altera Corporation. All Rights Reserved.\r
4 *\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
7 *\r
8 * 1. Redistributions of source code must retain the above copyright notice,\r
9 * this list of conditions and the following disclaimer.\r
10 *\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
14 *\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
17 *\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
27 * OF SUCH DAMAGE.\r
28 *\r
29 ******************************************************************************/\r
30 \r
31 #include    <stdint.h>\r
32 #include    <stdlib.h>\r
33 #include    <stdbool.h>\r
34 \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
39 #include    "hwlib.h"\r
40 #include    "alt_generalpurpose_io.h"\r
41 \r
42 \r
43 /****************************************************************************************/\r
44 /******************************* Useful local definitions *******************************/\r
45 /****************************************************************************************/\r
46 \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
51 \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
54 \r
55 \r
56 /****************************************************************************************/\r
57 /* alt_gpio_init() initializes the GPIO modules                                                                                 */\r
58 /****************************************************************************************/\r
59 \r
60 ALT_STATUS_CODE alt_gpio_init(void)\r
61 {\r
62                 // put GPIO modules into system manager reset if not already there\r
63         alt_gpio_uninit();\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
69 }\r
70 \r
71 \r
72 /****************************************************************************************/\r
73 /* alt_gpio_uninit() uninitializes the GPIO modules                                                             */\r
74 /****************************************************************************************/\r
75 \r
76 ALT_STATUS_CODE alt_gpio_uninit(void)\r
77 {\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
82                         ALT_GPIO_BITMASK);\r
83         return ALT_E_SUCCESS;\r
84 }\r
85 \r
86 \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
91 \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
94 {\r
95     volatile uint32_t   *addr;\r
96 \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
102 \r
103     alt_replbits_word(addr, mask, config);\r
104     return ALT_E_SUCCESS;\r
105 }\r
106 \r
107 \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
112 \r
113 uint32_t alt_gpio_port_datadir_get(ALT_GPIO_PORT_t gpio_pid,\r
114         uint32_t mask)\r
115 {\r
116     volatile uint32_t   *addr;\r
117 \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
121     else { return 0; }\r
122 \r
123     return alt_read_word(addr) & mask;\r
124 }\r
125 \r
126 \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
132 \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
135 {\r
136     volatile uint32_t   *addr;\r
137 \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
143 \r
144     alt_replbits_word(addr, mask, val);\r
145     return ALT_E_SUCCESS;\r
146 }\r
147 \r
148 \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
153 \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
158 \r
159 uint32_t alt_gpio_port_data_read(ALT_GPIO_PORT_t gpio_pid, uint32_t mask)\r
160 {\r
161     volatile uint32_t   *addr;\r
162 \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
166     else { return 0; }\r
167 \r
168     return alt_read_word(addr) & mask;\r
169 }\r
170 #endif\r
171 \r
172 \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
177 \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
180 {\r
181     volatile uint32_t   *addr;\r
182 \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
188 \r
189     alt_replbits_word(addr, mask, config);\r
190     return ALT_E_SUCCESS;\r
191 }\r
192 \r
193 \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
198 \r
199 uint32_t alt_gpio_port_int_type_get(ALT_GPIO_PORT_t gpio_pid,\r
200         uint32_t mask)\r
201 {\r
202     volatile uint32_t   *addr;\r
203 \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
207     else { return 0; }\r
208 \r
209     return alt_read_word(addr) & mask;\r
210 }\r
211 \r
212 \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
216 /* ( =1).                                                                               */\r
217 /****************************************************************************************/\r
218 \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
221 {\r
222     volatile uint32_t   *addr;\r
223 \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
229 \r
230     alt_replbits_word(addr, mask, config);\r
231     return ALT_E_SUCCESS;\r
232 }\r
233 \r
234 \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
241 \r
242 uint32_t alt_gpio_port_int_pol_get(ALT_GPIO_PORT_t gpio_pid,\r
243         uint32_t mask)\r
244 {\r
245     volatile uint32_t   *addr;\r
246 \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
250     else { return 0; }\r
251 \r
252     return alt_read_word(addr) & mask;\r
253 }\r
254 \r
255 \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
261 \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
264 {\r
265     volatile uint32_t   *addr;\r
266 \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
272 \r
273     alt_replbits_word(addr, mask, config);\r
274     return ALT_E_SUCCESS;\r
275 }\r
276 \r
277 \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
283 \r
284 uint32_t alt_gpio_port_debounce_get(ALT_GPIO_PORT_t gpio_pid,\r
285         uint32_t mask)\r
286 {\r
287     volatile uint32_t   *addr;\r
288 \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
292     else { return 0; }\r
293 \r
294     return alt_read_word(addr) & mask;\r
295 }\r
296 \r
297 \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
304 \r
305 ALT_STATUS_CODE alt_gpio_port_sync_set(ALT_GPIO_PORT_t gpio_pid, uint32_t config)\r
306 {\r
307     volatile uint32_t   *addr;\r
308 \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
314 \r
315     alt_write_word(addr, config);\r
316     return ALT_E_SUCCESS;\r
317 }\r
318 \r
319 \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
326 \r
327 ALT_STATUS_CODE alt_gpio_port_sync_get(ALT_GPIO_PORT_t gpio_pid)\r
328 {\r
329     volatile uint32_t   *addr;\r
330 \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
335 \r
336     return (alt_read_word(addr) != 0) ? ALT_E_TRUE : ALT_E_FALSE;\r
337 }\r
338 \r
339 \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
344 \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
348         uint32_t data)\r
349 {\r
350     ALT_STATUS_CODE     ret;\r
351 \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
355 \r
356         // set trigger type\r
357     if (ret == ALT_E_SUCCESS)\r
358     {\r
359         ret = alt_gpio_port_int_type_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(type));\r
360     }\r
361 \r
362         // set polarity\r
363     if (ret == ALT_E_SUCCESS)\r
364     {\r
365         alt_gpio_port_int_pol_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(pol));\r
366     }\r
367 \r
368         // set debounce\r
369     if (ret == ALT_E_SUCCESS)\r
370     {\r
371         alt_gpio_port_debounce_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(debounc));\r
372     }\r
373 \r
374         // set data output(s)\r
375     if (ret == ALT_E_SUCCESS)\r
376     {\r
377         alt_gpio_port_data_write(gpio_pid, mask, ALT_GPIO_ALLORNONE(data));\r
378     }\r
379 \r
380     if (ret == ALT_E_SUCCESS)\r
381     {\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
384     }\r
385 \r
386     return ret;\r
387 }\r
388 \r
389 \r
390 /****************************************************************************************/\r
391 /* Enables the specified GPIO data register interrupts.                                 */\r
392 /****************************************************************************************/\r
393 \r
394 ALT_STATUS_CODE alt_gpio_port_int_enable(ALT_GPIO_PORT_t gpio_pid, uint32_t config)\r
395 {\r
396     volatile uint32_t   *addr;\r
397 \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
403 \r
404     alt_replbits_word(addr, config, UINT32_MAX);\r
405     return ALT_E_SUCCESS;\r
406 }\r
407 \r
408 \r
409 /****************************************************************************************/\r
410 /* Disables the specified GPIO data module interrupts.                                  */\r
411 /****************************************************************************************/\r
412 \r
413 ALT_STATUS_CODE alt_gpio_port_int_disable(ALT_GPIO_PORT_t gpio_pid, uint32_t config)\r
414 {\r
415     volatile uint32_t   *addr;\r
416 \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
422 \r
423     alt_replbits_word(addr, config, 0);\r
424     return ALT_E_SUCCESS;\r
425 }\r
426 \r
427 \r
428 \r
429 /****************************************************************************************/\r
430 /* Get the current state of the specified GPIO port interrupts enables.                 */\r
431 /****************************************************************************************/\r
432 \r
433 uint32_t alt_gpio_port_int_enable_get(ALT_GPIO_PORT_t gpio_pid)\r
434 {\r
435     volatile uint32_t   *addr;\r
436 \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
440     else { return 0; }\r
441 \r
442     return alt_read_word(addr);\r
443 }\r
444 \r
445 \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
451 \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
454 {\r
455     volatile uint32_t   *addr;\r
456 \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
462 \r
463     alt_replbits_word(addr, mask, val);\r
464     return ALT_E_SUCCESS;\r
465 }\r
466 \r
467 \r
468 /****************************************************************************************/\r
469 /* Returns the interrupt source mask of the specified GPIO module.                      */\r
470 /****************************************************************************************/\r
471 \r
472 uint32_t alt_gpio_port_int_mask_get(ALT_GPIO_PORT_t gpio_pid)\r
473 {\r
474     volatile uint32_t   *addr;\r
475 \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
480 \r
481     return alt_read_word(addr);\r
482 }\r
483 \r
484 \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
489 \r
490 uint32_t alt_gpio_port_int_status_get(ALT_GPIO_PORT_t gpio_pid)\r
491 {\r
492     volatile uint32_t   *addr;\r
493 \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
498 \r
499     return alt_read_word(addr);\r
500 }\r
501 \r
502 \r
503 /****************************************************************************************/\r
504 /* Clear the interrupt pending status of selected signals of the specified GPIO         */\r
505 /* register.                                                                            */\r
506 /****************************************************************************************/\r
507 \r
508 ALT_STATUS_CODE alt_gpio_port_int_status_clear(ALT_GPIO_PORT_t gpio_pid,\r
509         uint32_t clrmask)\r
510 {\r
511     volatile uint32_t   *addr;\r
512 \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
518 \r
519     alt_write_word(addr, clrmask);\r
520     return ALT_E_SUCCESS;\r
521 }\r
522 \r
523 \r
524 /****************************************************************************************/\r
525 /*  alt_gpio_port_idcode_get() returns the ID code of the specified GPIO module.        */\r
526 /****************************************************************************************/\r
527 \r
528 uint32_t alt_gpio_port_idcode_get(ALT_GPIO_PORT_t gpio_pid)\r
529 {\r
530     volatile uint32_t   *addr;\r
531 \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
535     else { return 0; }\r
536 \r
537     return alt_read_word(addr);\r
538 }\r
539 \r
540 \r
541 /****************************************************************************************/\r
542 /* alt_gpio_port_ver_get() returns the version code of the specified GPIO module.       */\r
543 /****************************************************************************************/\r
544 \r
545 uint32_t alt_gpio_port_ver_get(ALT_GPIO_PORT_t gpio_pid)\r
546 {\r
547     volatile uint32_t   *addr;\r
548 \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
552     else { return 0; }\r
553 \r
554     return alt_read_word(addr);\r
555 }\r
556 \r
557 \r
558 /****************************************************************************************/\r
559 /* alt_gpio_bit_config() configures one bit (signal) of the GPIO ports.                 */\r
560 /****************************************************************************************/\r
561 \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
566 {\r
567     ALT_GPIO_PORT_t     pid;\r
568     uint32_t            mask;\r
569 \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
573 }\r
574 \r
575 \r
576 /****************************************************************************************/\r
577 /* Returns the configuration parameters of a given GPIO bit.                            */\r
578 /****************************************************************************************/\r
579 \r
580 ALT_STATUS_CODE alt_gpio_bitconfig_get(ALT_GPIO_1BIT_t signal_num,\r
581         ALT_GPIO_CONFIG_RECORD_t *config)\r
582 {\r
583     ALT_STATUS_CODE     ret = ALT_E_ERROR;\r
584     ALT_GPIO_PORT_t     pid;\r
585     uint32_t            mask, shift;\r
586 \r
587     if ((config != NULL) && (signal_num != ALT_END_OF_GPIO_SIGNALS) && (signal_num <= ALT_LAST_VALID_GPIO_BIT))\r
588     {\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
592         {\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
597 \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
603         }\r
604     }\r
605     return ret;\r
606 }\r
607 \r
608 \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
615 \r
616 ALT_STATUS_CODE alt_gpio_group_config(ALT_GPIO_CONFIG_RECORD_t* config_array, uint32_t len)\r
617 {\r
618     ALT_STATUS_CODE         ret = ALT_E_ERROR;\r
619 \r
620     if (config_array != NULL)\r
621     {\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
625         else\r
626         {\r
627             for (; (len-- > 0) && (config_array->signal_number != ALT_END_OF_GPIO_SIGNALS) && (config_array != NULL); config_array++)\r
628             {\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
633                 {\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
640                 }\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
643                 {\r
644                     ret = ALT_E_ERROR;\r
645                     break;\r
646                 }\r
647             }\r
648         }\r
649     }\r
650     return ret;\r
651 }\r
652 \r
653 \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
661 /* function.                                                                            */\r
662 /****************************************************************************************/\r
663 \r
664 ALT_STATUS_CODE alt_gpio_group_config_get(ALT_GPIO_CONFIG_RECORD_t *config_array,\r
665         uint32_t len)\r
666 {\r
667     ALT_STATUS_CODE     ret = ALT_E_ERROR;\r
668 \r
669     if ((config_array != NULL) && (config_array->signal_number == ALT_END_OF_GPIO_SIGNALS))\r
670     {\r
671         ret = ALT_E_SUCCESS;\r
672     }\r
673     else\r
674     {\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
677         {\r
678             ret = alt_gpio_bitconfig_get(config_array->signal_number, config_array);\r
679             config_array++;\r
680             if (ret != ALT_E_SUCCESS) { break; }\r
681         }\r
682     }\r
683     return ret;\r
684 }\r
685 \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
693 /* operation.                                                                           */\r
694 /****************************************************************************************/\r
695 \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
698 {\r
699     ALT_STATUS_CODE     ret = ALT_E_ERROR;\r
700 \r
701     if ((config_array != NULL) && (pinid_array != NULL) && (*pinid_array == ALT_END_OF_GPIO_SIGNALS))\r
702     {\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
706     }\r
707     else\r
708     {\r
709         for ( ;(len > 0) && (pinid_array != NULL) && (*pinid_array != ALT_END_OF_GPIO_SIGNALS) && (config_array != NULL); len--)\r
710         {\r
711             ret = alt_gpio_bitconfig_get(*pinid_array, config_array);\r
712             config_array++;\r
713             pinid_array++;\r
714             if (ret != ALT_E_SUCCESS) { break; }\r
715         }\r
716     }\r
717     return ret;\r
718 }\r
719 \r
720 \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
725 \r
726 ALT_GPIO_PORT_t alt_gpio_bit_to_pid(ALT_GPIO_1BIT_t pin_num)\r
727 {\r
728     ALT_GPIO_PORT_t     pid = ALT_GPIO_PORT_UNKNOWN;\r
729 \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
733     return pid;\r
734 }\r
735 \r
736 \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
741 \r
742 ALT_GPIO_PORTBIT_t alt_gpio_bit_to_port_pin(ALT_GPIO_1BIT_t pin_num)\r
743 {\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
749 }\r
750 \r
751 \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
757 \r
758 ALT_GPIO_1BIT_t alt_gpio_port_pin_to_bit(ALT_GPIO_PORT_t pid,\r
759         uint32_t bitmask)\r
760 {\r
761     uint32_t    i;\r
762 \r
763     for (i=0; i <= ALT_GPIO_BITNUM_MAX ;i++)\r
764     {\r
765         if (bitmask & 0x00000001)\r
766         {\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
772         }\r
773         bitmask >>= 1;\r
774     }\r
775     return ALT_END_OF_GPIO_SIGNALS;\r
776 }\r
777 \r