Test application for UV, IR, Light and Temperature sensors
[lpc82x] / core / pio.c
1 /****************************************************************************
2  *  core/pio.c
3  *
4  * Copyright 2016 Nathael Pajani <nathael.pajani@ed3l.fr>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  *************************************************************************** */
21 /***************************************************************************** */
22 /*                GPIOs                                                        */
23 /***************************************************************************** */
25 /*   Public access to Pins setup
26  * Refer to LPC82x documentation (UM10800.pdf) for more information.
27  */
30 #include "lib/stdint.h"
31 #include "core/system.h"
32 #include "core/pio.h"
33 #include "lib/string.h"
37 /***************************************************************************** */
38 static volatile uint32_t* pio_regs_handles_port0[PORT0_NB_PINS] = {
39         &(LPC_IO_CONTROL->pio0_0),
40         &(LPC_IO_CONTROL->pio0_1),
41         &(LPC_IO_CONTROL->pio0_2),
42         &(LPC_IO_CONTROL->pio0_3),
43         &(LPC_IO_CONTROL->pio0_4),
44         &(LPC_IO_CONTROL->pio0_5),
45         &(LPC_IO_CONTROL->pio0_6),
46         &(LPC_IO_CONTROL->pio0_7),
47         &(LPC_IO_CONTROL->pio0_8),
48         &(LPC_IO_CONTROL->pio0_9),
49         &(LPC_IO_CONTROL->pio0_10),
50         &(LPC_IO_CONTROL->pio0_11),
51         &(LPC_IO_CONTROL->pio0_12),
52         &(LPC_IO_CONTROL->pio0_13),
53         &(LPC_IO_CONTROL->pio0_14),
54         &(LPC_IO_CONTROL->pio0_15),
55         &(LPC_IO_CONTROL->pio0_16),
56         &(LPC_IO_CONTROL->pio0_17),
57         &(LPC_IO_CONTROL->pio0_18),
58         &(LPC_IO_CONTROL->pio0_19),
59         &(LPC_IO_CONTROL->pio0_20),
60         &(LPC_IO_CONTROL->pio0_21),
61         &(LPC_IO_CONTROL->pio0_22),
62         &(LPC_IO_CONTROL->pio0_23),
63         &(LPC_IO_CONTROL->pio0_24),
64         &(LPC_IO_CONTROL->pio0_25),
65         &(LPC_IO_CONTROL->pio0_26),
66         &(LPC_IO_CONTROL->pio0_27),
67         &(LPC_IO_CONTROL->pio0_28),
68 };
70 /* IO config clock */
71 /* To change GPIO config the io config block must be powered on */
72 static void io_config_clk_on(void)
73 {
74     subsystem_power(LPC_SYS_ABH_CLK_CTRL_IO_CONFIG, 1);
75     subsystem_power(LPC_SYS_ABH_CLK_CTRL_SWM, 1);
76 }
77 static void io_config_clk_off(void)
78 {
79     subsystem_power(LPC_SYS_ABH_CLK_CTRL_IO_CONFIG, 0);
80     subsystem_power(LPC_SYS_ABH_CLK_CTRL_SWM, 0);
81 }
84 /* Simple copy function. */
85 void pio_copy(struct pio* dst, const struct pio* src)
86 {
87         if ((dst == NULL) || (src == NULL)) {
88                 return;
89         }
90         memcpy(dst, src, sizeof(struct pio));
91 }
93 /* Configure the pin in the requested function and mode. */
94 static void config_pio_safe(const struct pio* pp, const struct pin_matrix_entry* me, uint16_t mode)
95 {
96         struct lpc_switch_matrix* matrix = LPC_SWITCH_MATRIX;
97         volatile uint32_t* handle = NULL;
99         if (pp->pin >= PORT0_NB_PINS) {
100                 return;
101         }
102         /* Movable (offset0 & 0x80) or Fixed pin function */
103         if (pp->offset0 & 0x80) {
104                 /* Disable fixed pin functions for this pin */
105                 if ((pp->offset0 & 0x7F) <= 31) {
106                         matrix->pin_enable[0] |= (1 << (pp->offset0 & 0x7F));
107                 }
108                 if (pp->offset1 <= 31) {
109                         matrix->pin_enable[0] |= (1 << pp->offset1);
110                 }
111                 /* Assign the function to the pin if not a GPIO or fixed pin function */
112                 if ((me != NULL) && (me->reg_offset < LPC_MATRIX_NB_PIN_ASSIGN)) {
113                         matrix->pin_assign[me->reg_offset] &= ~(0xFF << me->bit_shift);
114                         matrix->pin_assign[me->reg_offset] |= (pp->pin << me->bit_shift);
115                 }
116                 /* Configure the GPIO mode */
117                 handle = pio_regs_handles_port0[pp->pin];
118                 *handle = mode;
119         } else {
120                 /* Maybe disable the other fixed pin entry ? */
121                 if (pp->offset1 <= 31) {
122                         matrix->pin_enable[0] |= (1 << pp->offset1);
123                 }
124                 /* Enable our own fixed pin entry */
125                 if (pp->offset0 <= 31) {
126                         matrix->pin_enable[0] &= ~(1 << pp->offset0);
127                 }
128         }
131 void config_pio(const struct pio* pp, const struct pin_matrix_entry* matrix, uint16_t mode)
133         if (pp == NULL) {
134                 return;
135         }
137         /* Make sure IO_Config is clocked */
138         io_config_clk_on();
140         config_pio_safe(pp, matrix, mode);
142         /* Config done, power off IO_CONFIG block */
143         io_config_clk_off();
147 void set_pins(const struct pio_config* pins)
149         int i = 0;
150         /* Make sure IO_Config is clocked */
151         io_config_clk_on();
152         for (i = 0; pins[i].pio.pin != 0xFF; i++) {
153                 config_pio_safe(&(pins[i].pio), &(pins[i].matrix), pins[i].mode);
154         }
155         /* Config done, power off IO_CONFIG block */
156         io_config_clk_off();