Added backlight, reset, triangle and corner commands
[hackover2013-badge-firmware.git] / core / gpio / gpio.c
1 /**************************************************************************/
2 /*!
3 @file gpio.c
4 @author K. Townsend (microBuilder.eu)
5 @date 22 March 2010
6 @version 0.10
7
8 @section DESCRIPTION
9
10 Controls the general purpose digital IO.
11
12 @section LICENSE
13
14 Software License Agreement (BSD License)
15
16 Copyright (c) 2010, microBuilder SARL
17 All rights reserved.
18
19 Redistribution and use in source and binary forms, with or without
20 modification, are permitted provided that the following conditions are met:
21 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
23 2. Redistributions in binary form must reproduce the above copyright
24 notice, this list of conditions and the following disclaimer in the
25 documentation and/or other materials provided with the distribution.
26 3. Neither the name of the copyright holders nor the
27 names of its contributors may be used to endorse or promote products
28 derived from this software without specific prior written permission.
29
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
31 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41 /**************************************************************************/
42
43 #include "gpio.h"
44
45 #ifdef CFG_CHIBI
46 #include "drivers/chibi/chb_drvr.h"
47 volatile uint32_t chibi_counter = 0;
48 #endif
49
50 #ifdef CFG_ALTRESET
51 #include "core/cpu/cpu.h"
52 #endif
53
54 static bool _gpioInitialised = false;
55
56 /**************************************************************************/
57 /*!
58 @brief IRQ Handler for GPIO port 0 (currently checks pin 0.1)
59 */
60 /**************************************************************************/
61 void PIOINT0_IRQHandler(void)
62 {
63 uint32_t regVal;
64
65 regVal = gpioIntStatus(0, 1);
66 if (regVal)
67 {
68 gpioIntClear(0, 1);
69 }
70 return;
71 }
72
73 /**************************************************************************/
74 /*!
75 @brief IRQ Handler for GPIO port 1 (currently checks pin 1.1)
76 */
77 /**************************************************************************/
78 void PIOINT1_IRQHandler(void)
79 {
80 uint32_t regVal;
81
82 #if defined CFG_ALTRESET && CFG_ALTRESET_PORT == 1
83 regVal = gpioIntStatus(CFG_ALTRESET_PORT, CFG_ALTRESET_PIN);
84 if (regVal)
85 {
86 // Cause a reset and wait
87 cpuReset();
88 }
89 #endif
90
91 #ifdef CFG_CHIBI
92 // Check for interrupt on 1.8
93 regVal = gpioIntStatus(1, 8);
94 if (regVal)
95 {
96 chibi_counter++;
97 chb_ISR_Handler();
98 gpioIntClear(1, 8);
99 }
100 #else
101 regVal = gpioIntStatus(1, 1);
102 if ( regVal )
103 {
104 gpioIntClear(1, 1);
105 }
106 #endif
107
108 return;
109 }
110
111 /**************************************************************************/
112 /*!
113 @brief IRQ Handler for GPIO port 2 (currently checks pin 2.1)
114 */
115 /**************************************************************************/
116 void PIOINT2_IRQHandler(void)
117 {
118 uint32_t regVal;
119
120 regVal = gpioIntStatus(2, 1);
121 if ( regVal )
122 {
123 gpioIntClear(2, 1);
124 }
125 return;
126 }
127
128 /**************************************************************************/
129 /*!
130 @brief IRQ Handler for GPIO port 3 (currently checks pin 3.1)
131 */
132 /**************************************************************************/
133 void PIOINT3_IRQHandler(void)
134 {
135 uint32_t regVal;
136
137 regVal = gpioIntStatus(3, 1);
138 if ( regVal )
139 {
140 gpioIntClear(3, 1);
141 }
142 return;
143 }
144
145 /**************************************************************************/
146 /*!
147 @brief Initialises GPIO and enables the GPIO interrupt
148 handler for all GPIO ports.
149 */
150 /**************************************************************************/
151 void gpioInit (void)
152 {
153 /* Enable AHB clock to the GPIO domain. */
154 SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_GPIO);
155
156 /* Set up NVIC when I/O pins are configured as external interrupts. */
157 NVIC_EnableIRQ(EINT0_IRQn);
158 NVIC_EnableIRQ(EINT1_IRQn);
159 NVIC_EnableIRQ(EINT2_IRQn);
160 NVIC_EnableIRQ(EINT3_IRQn);
161
162 /* Set initialisation flag */
163 _gpioInitialised = true;
164
165 return;
166 }
167
168 /**************************************************************************/
169 /*!
170 @brief Sets the direction (input/output) for a specific port pin
171
172 @param[in] portNum
173 The port number (0..3)
174 @param[in] bitPos
175 The bit position (0..11)
176 @param[in] dir
177 The pin direction (gpioDirection_Input or
178 gpioDirection_Output)
179 */
180 /**************************************************************************/
181 void gpioSetDir (uint32_t portNum, uint32_t bitPos, gpioDirection_t dir)
182 {
183 if (!_gpioInitialised) gpioInit();
184
185 // Get the appropriate register (handled this way to optimise code size)
186 REG32 *gpiodir = &GPIO_GPIO0DIR;
187 switch (portNum)
188 {
189 case 0:
190 gpiodir = &GPIO_GPIO0DIR;
191 break;
192 case 1:
193 gpiodir = &GPIO_GPIO1DIR;
194 break;
195 case 2:
196 gpiodir = &GPIO_GPIO2DIR;
197 break;
198 case 3:
199 gpiodir = &GPIO_GPIO3DIR;
200 break;
201 }
202
203 // Toggle dir
204 dir == gpioDirection_Output ? (*gpiodir |= (1 << bitPos)) : (*gpiodir &= ~(1 << bitPos));
205 }
206
207 /**************************************************************************/
208 /*!
209 @brief Gets the value for a specific port pin
210
211 @param[in] portNum
212 The port number (0..3)
213 @param[in] bitPos
214 The bit position (0..31)
215
216 @return The current value for the specified port pin (0..1)
217 */
218 /**************************************************************************/
219 uint32_t gpioGetValue (uint32_t portNum, uint32_t bitPos)
220 {
221 if (!_gpioInitialised) gpioInit();
222
223 uint32_t value = 0;
224
225 switch (portNum)
226 {
227 case 0:
228 value = (GPIO_GPIO0DATA & (1 << bitPos)) ? 1 : 0;
229 break;
230 case 1:
231 value = (GPIO_GPIO1DATA & (1 << bitPos)) ? 1 : 0;
232 break;
233 case 2:
234 value = (GPIO_GPIO2DATA & (1 << bitPos)) ? 1 : 0;
235 break;
236 case 3:
237 value = (GPIO_GPIO3DATA & (1 << bitPos)) ? 1 : 0;
238 break;
239 default:
240 break;
241 }
242
243 return value;
244 }
245
246 /**************************************************************************/
247 /*!
248 @brief Sets the value for a specific port pin (only relevant when a
249 pin is configured as output).
250
251 @param[in] portNum
252 The port number (0..3)
253 @param[in] bitPos
254 The bit position (0..31)
255 @param[in] bitValue
256 The value to set for the specified bit (0..1). 0 will set
257 the pin low and 1 will set the pin high.
258 */
259 /**************************************************************************/
260 void gpioSetValue (uint32_t portNum, uint32_t bitPos, uint32_t bitVal)
261 {
262 if (!_gpioInitialised) gpioInit();
263
264 // Get the appropriate register (handled this way to optimise code size)
265 REG32 *gpiodata = &GPIO_GPIO0DATA;
266 switch (portNum)
267 {
268 case 0:
269 gpiodata = &GPIO_GPIO0DATA;
270 break;
271 case 1:
272 gpiodata = &GPIO_GPIO1DATA;
273 break;
274 case 2:
275 gpiodata = &GPIO_GPIO2DATA;
276 break;
277 case 3:
278 gpiodata = &GPIO_GPIO3DATA;
279 break;
280 }
281
282 // Toggle value
283 bitVal == 1 ? (*gpiodata |= (1 << bitPos)) : (*gpiodata &= ~(1 << bitPos));
284 }
285
286 /**************************************************************************/
287 /*!
288 @brief Sets the interrupt sense, event, etc.
289
290 @param[in] portNum
291 The port number (0..3)
292 @param[in] bitPos
293 The bit position (0..31)
294 @param[in] sense
295 Whether the interrupt should be configured as edge or level
296 sensitive.
297 @param[in] edge
298 Whether one edge or both trigger an interrupt.
299 @param[in] event
300 Whether the rising or the falling edge (high or low)
301 should be used to trigger the interrupt.
302
303 @section Example
304
305 @code
306 // Initialise gpio
307 gpioInit();
308 // Set GPIO1.8 to input
309 gpioSetDir(1, 8, gpioDirection_Input);
310 // Disable the internal pullup/down resistor on P1.8
311 gpioSetPullup (&IOCON_PIO1_8, gpioPullupMode_Inactive);
312 // Setup an interrupt on GPIO1.8
313 gpioSetInterrupt(1, // Port
314 8, // Pin
315 gpioInterruptSense_Edge, // Edge/Level Sensitive
316 gpioInterruptEdge_Single, // Single/Double Edge
317 gpioInterruptEvent_ActiveHigh); // Rising/Falling
318 // Enable the interrupt
319 gpioIntEnable(1, 8);
320 @endcode
321 */
322 /**************************************************************************/
323 void gpioSetInterrupt (uint32_t portNum, uint32_t bitPos, gpioInterruptSense_t sense, gpioInterruptEdge_t edge, gpioInterruptEvent_t event)
324 {
325 if (!_gpioInitialised) gpioInit();
326
327 // Get the appropriate register (handled this way to optimise code size)
328 REG32 *gpiois = &GPIO_GPIO0IS; // Interrupt sense (edge or level sensitive)
329 REG32 *gpioibe = &GPIO_GPIO0IBE; // Interrupt both edges (0 = int controlled by GPIOIEV, 1 = both edges trigger interrupt)
330 REG32 *gpioiev = &GPIO_GPIO0IEV; // 0 = falling edge or low, 1 = rising edge or high (depending on GPIOIS)
331 switch (portNum)
332 {
333 case 0:
334 gpiois = &GPIO_GPIO0IS;
335 gpioibe = &GPIO_GPIO0IBE;
336 gpioiev = &GPIO_GPIO0IEV;
337 break;
338 case 1:
339 gpiois = &GPIO_GPIO1IS;
340 gpioibe = &GPIO_GPIO1IBE;
341 gpioiev = &GPIO_GPIO1IEV;
342 break;
343 case 2:
344 gpiois = &GPIO_GPIO2IS;
345 gpioibe = &GPIO_GPIO2IBE;
346 gpioiev = &GPIO_GPIO2IEV;
347 break;
348 case 3:
349 gpiois = &GPIO_GPIO3IS;
350 gpioibe = &GPIO_GPIO3IBE;
351 gpioiev = &GPIO_GPIO3IEV;
352 break;
353 }
354
355
356 if (sense == gpioInterruptSense_Edge)
357 {
358 *gpiois &= ~(0x1<<bitPos);
359 edge == gpioInterruptEdge_Single ? (*gpioibe &= ~(0x1<<bitPos)) : (*gpioibe |= (0x1<<bitPos));
360 }
361 else
362 {
363 *gpiois |= (0x1<<bitPos);
364 }
365
366 event == gpioInterruptEvent_ActiveHigh ? (*gpioiev &= ~(0x1<<bitPos)) : (*gpioiev |= (0x1<<bitPos));
367
368 return;
369 }
370
371 /**************************************************************************/
372 /*!
373 @brief Enables the interrupt mask for a specific port pin
374
375 @param[in] portNum
376 The port number (0..3)
377 @param[in] bitPos
378 The bit position (0..31)
379 */
380 /**************************************************************************/
381 void gpioIntEnable (uint32_t portNum, uint32_t bitPos)
382 {
383 if (!_gpioInitialised) gpioInit();
384
385 switch (portNum)
386 {
387 case 0:
388 GPIO_GPIO0IE |= (0x1<<bitPos);
389 break;
390 case 1:
391 GPIO_GPIO1IE |= (0x1<<bitPos);
392 break;
393 case 2:
394 GPIO_GPIO2IE |= (0x1<<bitPos);
395 break;
396 case 3:
397 GPIO_GPIO3IE |= (0x1<<bitPos);
398 break;
399 default:
400 break;
401 }
402 return;
403 }
404
405 /**************************************************************************/
406 /*!
407 @brief Disables the interrupt mask for a specific port pin
408
409 @param[in] portNum
410 The port number (0..3)
411 @param[in] bitPos
412 The bit position (0..31)
413 */
414 /**************************************************************************/
415 void gpioIntDisable (uint32_t portNum, uint32_t bitPos)
416 {
417 if (!_gpioInitialised) gpioInit();
418
419 switch (portNum)
420 {
421 case 0:
422 GPIO_GPIO0IE &= ~(0x1<<bitPos);
423 break;
424 case 1:
425 GPIO_GPIO1IE &= ~(0x1<<bitPos);
426 break;
427 case 2:
428 GPIO_GPIO2IE &= ~(0x1<<bitPos);
429 break;
430 case 3:
431 GPIO_GPIO3IE &= ~(0x1<<bitPos);
432 break;
433 default:
434 break;
435 }
436 return;
437 }
438
439 /**************************************************************************/
440 /*!
441 @brief Gets the interrupt status for a specific port pin
442
443 @param[in] portNum
444 The port number (0..3)
445 @param[in] bitPos
446 The bit position (0..31)
447
448 @return The interrupt status for the specified port pin (0..1)
449 */
450 /**************************************************************************/
451 uint32_t gpioIntStatus (uint32_t portNum, uint32_t bitPos)
452 {
453 if (!_gpioInitialised) gpioInit();
454
455 uint32_t regVal = 0;
456
457 switch (portNum)
458 {
459 case 0:
460 if (GPIO_GPIO0MIS & (0x1<<bitPos))
461 {
462 regVal = 1;
463 }
464 break;
465 case 1:
466 if (GPIO_GPIO1MIS & (0x1<<bitPos))
467 {
468 regVal = 1;
469 }
470 break;
471 case 2:
472 if (GPIO_GPIO2MIS & (0x1<<bitPos))
473 {
474 regVal = 1;
475 }
476 break;
477 case 3:
478 if (GPIO_GPIO3MIS & (0x1<<bitPos))
479 {
480 regVal = 1;
481 }
482 break;
483 default:
484 break;
485 }
486 return ( regVal );
487 }
488
489 /**************************************************************************/
490 /*!
491 @brief Clears the interrupt for a port pin
492
493 @param[in] portNum
494 The port number (0..3)
495 @param[in] bitPos
496 The bit position (0..31)
497 */
498 /**************************************************************************/
499 void gpioIntClear (uint32_t portNum, uint32_t bitPos)
500 {
501 if (!_gpioInitialised) gpioInit();
502
503 switch (portNum)
504 {
505 case 0:
506 GPIO_GPIO0IC |= (0x1<<bitPos);
507 break;
508 case 1:
509 GPIO_GPIO1IC |= (0x1<<bitPos);
510 break;
511 case 2:
512 GPIO_GPIO2IC |= (0x1<<bitPos);
513 break;
514 case 3:
515 GPIO_GPIO3IC |= (0x1<<bitPos);
516 break;
517 default:
518 break;
519 }
520 return;
521 }
522
523 /**************************************************************************/
524 /*!
525 @brief Configures the internal pullup/down resistor for GPIO pins
526 (only relevant for pins configured as inputs)
527
528 @param[in] ioconReg
529 A pointer to the IOCON registry value corresponding to
530 the pin you wish to change (for example: &IOCON_PIO2_0
531 for GPIO pin 2.0).
532 @param[in] mode
533 The 'mode' that the pin should be set to, which must be
534 correspond to a value defined in gpioPullupMode_t
535
536 @warning By default, all GPIO pins have the internal pull-up
537 resistor enabled. This may cause unusual behaviour if
538 care isn't taken to set the internal resistor to an
539 appropriate state.
540
541 @section Example
542
543 @code
544 // Initialise gpio
545 gpioInit();
546 // Set GPIO1.8 to input
547 gpioSetDir(1, 8, gpioDirection_Input);
548 // Disable the internal pullup/down resistor on P1.8
549 gpioSetPullup(&IOCON_PIO1_8, gpioPullupMode_Inactive);
550 @endcode
551 */
552 /**************************************************************************/
553 void gpioSetPullup (volatile uint32_t *ioconReg, gpioPullupMode_t mode)
554 {
555 if (!_gpioInitialised) gpioInit();
556
557 // ToDo: Disable interrupts while we are doing this?
558
559 *ioconReg &= ~(IOCON_COMMON_MODE_MASK);
560 *ioconReg |= mode;
561
562 // ToDo: Re-enable interrupts?
563 };
This page took 0.093854 seconds and 5 git commands to generate.