blob: aef0f45325c045fac4380d17b621e772345fed7d [file] [log] [blame]
Christina Quast2d18f172014-11-22 19:48:48 +01001/* ----------------------------------------------------------------------------
2 * ATMEL Microcontroller Software Support
3 * ----------------------------------------------------------------------------
4 * Copyright (c) 2010, Atmel Corporation
5 *
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * - Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the disclaimer below.
13 *
14 * Atmel's name may not be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * ----------------------------------------------------------------------------
28 */
29
30/** \file */
31
32/*----------------------------------------------------------------------------
33 * Headers
34 *----------------------------------------------------------------------------*/
35#include "include/chip.h"
36#include "include/pio.h"
37#include "include/pmc.h"
38
39
40/*----------------------------------------------------------------------------
41 * Local functions
42 *----------------------------------------------------------------------------*/
43
44/**
45 * \brief Configures one or more pin(s) of a PIO controller as being controlled by
46 * peripheral A. Optionally, the corresponding internal pull-up(s) can be enabled.
47 *
48 * \param pio Pointer to a PIO controller.
49 * \param mask Bitmask of one or more pin(s) to configure.
50 * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
51 * configured.
52 */
53static void PIO_SetPeripheralA(
54 Pio *pio,
55 unsigned int mask,
56 unsigned char enablePullUp)
57{
58 unsigned int abcdsr;
59 /* Disable interrupts on the pin(s) */
60 pio->PIO_IDR = mask;
61
62 /* Enable the pull-up(s) if necessary */
63 if (enablePullUp) {
64 pio->PIO_PUER = mask;
65 }
66 else {
67
68 pio->PIO_PUDR = mask;
69 }
70
71 abcdsr = pio->PIO_ABCDSR[0];
72 pio->PIO_ABCDSR[0] &= (~mask & abcdsr);
73 abcdsr = pio->PIO_ABCDSR[1];
74 pio->PIO_ABCDSR[1] &= (~mask & abcdsr);
75 pio->PIO_PDR = mask;
76}
77
78/**
79 * \brief Configures one or more pin(s) of a PIO controller as being controlled by
80 * peripheral B. Optionally, the corresponding internal pull-up(s) can be enabled.
81 *
82 * \param pio Pointer to a PIO controller.
83 * \param mask Bitmask of one or more pin(s) to configure.
84 * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
85 * configured.
86 */
87static void PIO_SetPeripheralB(
88 Pio *pio,
89 unsigned int mask,
90 unsigned char enablePullUp)
91{
92 unsigned int abcdsr;
93 /* Disable interrupts on the pin(s) */
94 pio->PIO_IDR = mask;
95
96 /* Enable the pull-up(s) if necessary */
97 if (enablePullUp) {
98
99 pio->PIO_PUER = mask;
100 }
101 else {
102
103 pio->PIO_PUDR = mask;
104 }
105
106 abcdsr = pio->PIO_ABCDSR[0];
107 pio->PIO_ABCDSR[0] = (mask | abcdsr);
108 abcdsr = pio->PIO_ABCDSR[1];
109 pio->PIO_ABCDSR[1] &= (~mask & abcdsr);
110
111 pio->PIO_PDR = mask;
112}
113
114/**
115 * \brief Configures one or more pin(s) of a PIO controller as being controlled by
116 * peripheral C. Optionally, the corresponding internal pull-up(s) can be enabled.
117 *
118 * \param pio Pointer to a PIO controller.
119 * \param mask Bitmask of one or more pin(s) to configure.
120 * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
121 * configured.
122 */
123static void PIO_SetPeripheralC(
124 Pio *pio,
125 unsigned int mask,
126 unsigned char enablePullUp)
127{
128 unsigned int abcdsr;
129 /* Disable interrupts on the pin(s) */
130 pio->PIO_IDR = mask;
131
132 /* Enable the pull-up(s) if necessary */
133 if (enablePullUp) {
134
135 pio->PIO_PUER = mask;
136 }
137 else {
138
139 pio->PIO_PUDR = mask;
140 }
141
142 abcdsr = pio->PIO_ABCDSR[0];
143 pio->PIO_ABCDSR[0] &= (~mask & abcdsr);
144 abcdsr = pio->PIO_ABCDSR[1];
145 pio->PIO_ABCDSR[1] = (mask | abcdsr);
146
147 pio->PIO_PDR = mask;
148}
149
150/**
151 * \brief Configures one or more pin(s) of a PIO controller as being controlled by
152 * peripheral D. Optionally, the corresponding internal pull-up(s) can be enabled.
153 *
154 * \param pio Pointer to a PIO controller.
155 * \param mask Bitmask of one or more pin(s) to configure.
156 * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
157 * configured.
158 */
159static void PIO_SetPeripheralD(
160 Pio *pio,
161 unsigned int mask,
162 unsigned char enablePullUp)
163{
164 unsigned int abcdsr;
165 /* Disable interrupts on the pin(s) */
166 pio->PIO_IDR = mask;
167
168 /* Enable the pull-up(s) if necessary */
169 if (enablePullUp) {
170
171 pio->PIO_PUER = mask;
172 }
173 else {
174
175 pio->PIO_PUDR = mask;
176 }
177
178 abcdsr = pio->PIO_ABCDSR[0];
179 pio->PIO_ABCDSR[0] = (mask | abcdsr);
180 abcdsr = pio->PIO_ABCDSR[1];
181 pio->PIO_ABCDSR[1] = (mask | abcdsr);
182
183 pio->PIO_PDR = mask;
184}
185
186/**
187 * \brief Configures one or more pin(s) or a PIO controller as inputs. Optionally,
188 * the corresponding internal pull-up(s) and glitch filter(s) can be enabled.
189 *
190 * \param pio Pointer to a PIO controller.
191 * \param mask Bitmask indicating which pin(s) to configure as input(s).
192 * \param enablePullUp Indicates if the internal pull-up(s) must be enabled.
193 * \param enableFilter Indicates if the glitch filter(s) must be enabled.
194 */
195static void PIO_SetInput(
196 Pio *pio,
197 unsigned int mask,
198 unsigned char attribute)
199{
200 /* Disable interrupts */
201 pio->PIO_IDR = mask;
202
203 /* Enable pull-up(s) if necessary */
204 if (attribute & PIO_PULLUP)
205 pio->PIO_PUER = mask;
206 else
207 pio->PIO_PUDR = mask;
208
209 /* Enable Input Filter if necessary */
210 if (attribute & (PIO_DEGLITCH | PIO_DEBOUNCE))
211 pio->PIO_IFER = mask;
212 else
213 pio->PIO_IFDR = mask;
214
215 /* Enable de-glitch or de-bounce if necessary */
216 if (attribute & PIO_DEGLITCH)
217 {
218 pio->PIO_IFSCDR = mask;
219 }
220 else
221 {
222 if (attribute & PIO_DEBOUNCE)
223 {
224 pio->PIO_IFSCER = mask;
225 }
226 }
227
228 /* Configure pin as input */
229 pio->PIO_ODR = mask;
230 pio->PIO_PER = mask;
231}
232
233/**
234 * \brief Configures one or more pin(s) of a PIO controller as outputs, with the
235 * given default value. Optionally, the multi-drive feature can be enabled
236 * on the pin(s).
237 *
238 * \param pio Pointer to a PIO controller.
239 * \param mask Bitmask indicating which pin(s) to configure.
240 * \param defaultValue Default level on the pin(s).
241 * \param enableMultiDrive Indicates if the pin(s) shall be configured as
242 * open-drain.
243 * \param enablePullUp Indicates if the pin shall have its pull-up activated.
244 */
245static void PIO_SetOutput(
246 Pio *pio,
247 unsigned int mask,
248 unsigned char defaultValue,
249 unsigned char enableMultiDrive,
250 unsigned char enablePullUp)
251{
252 /* Disable interrupts */
253 pio->PIO_IDR = mask;
254
255 /* Enable pull-up(s) if necessary */
256 if (enablePullUp) {
257
258 pio->PIO_PUER = mask;
259 }
260 else {
261
262 pio->PIO_PUDR = mask;
263 }
264
265 /* Enable multi-drive if necessary */
266 if (enableMultiDrive) {
267
268 pio->PIO_MDER = mask;
269 }
270 else {
271
272 pio->PIO_MDDR = mask;
273 }
274
275 /* Set default value */
276 if (defaultValue) {
277
278 pio->PIO_SODR = mask;
279 }
280 else {
281
282 pio->PIO_CODR = mask;
283 }
284
285 /* Configure pin(s) as output(s) */
286 pio->PIO_OER = mask;
287 pio->PIO_PER = mask;
288}
289
290/*----------------------------------------------------------------------------
291 * Global functions
292 *----------------------------------------------------------------------------*/
293
294/**
295 * \brief Configures a list of Pin instances, each of which can either hold a single
296 * pin or a group of pins, depending on the mask value; all pins are configured
297 * by this function. The size of the array must also be provided and is easily
298 * computed using PIO_LISTSIZE whenever its length is not known in advance.
299 *
300 * \param list Pointer to a list of Pin instances.
301 * \param size Size of the Pin list (calculated using PIO_LISTSIZE).
302 *
303 * \return 1 if the pins have been configured properly; otherwise 0.
304 */
305uint8_t PIO_Configure( const Pin *list, uint32_t size )
306{
307 /* Configure pins */
308 while ( size > 0 )
309 {
310 switch ( list->type )
311 {
312
313 case PIO_PERIPH_A:
314 PIO_SetPeripheralA(list->pio,
315 list->mask,
316 (list->attribute & PIO_PULLUP) ? 1 : 0);
317 break;
318
319 case PIO_PERIPH_B:
320 PIO_SetPeripheralB(list->pio,
321 list->mask,
322 (list->attribute & PIO_PULLUP) ? 1 : 0);
323 break;
324
325 case PIO_PERIPH_C:
326 PIO_SetPeripheralC(list->pio,
327 list->mask,
328 (list->attribute & PIO_PULLUP) ? 1 : 0);
329 break;
330
331 case PIO_PERIPH_D:
332 PIO_SetPeripheralD(list->pio,
333 list->mask,
334 (list->attribute & PIO_PULLUP) ? 1 : 0);
335 break;
336 case PIO_INPUT:
337 PMC_EnablePeripheral(list->id);
338 PIO_SetInput(list->pio,
339 list->mask,
340 list->attribute);
341 break;
342
343 case PIO_OUTPUT_0:
344 case PIO_OUTPUT_1:
345 PIO_SetOutput(list->pio,
346 list->mask,
347 (list->type == PIO_OUTPUT_1),
348 (list->attribute & PIO_OPENDRAIN) ? 1 : 0,
349 (list->attribute & PIO_PULLUP) ? 1 : 0);
350 break;
351
352 default: return 0;
353 }
354
355 list++;
356 size--;
357 }
358
359 return 1;
360}
361
362/**
363 * \brief Sets a high output level on all the PIOs defined in the given Pin instance.
364 * This has no immediate effects on PIOs that are not output, but the PIO
365 * controller will memorize the value they are changed to outputs.
366 *
367 * \param pin Pointer to a Pin instance describing one or more pins.
368 */
369void PIO_Set(const Pin *pin)
370{
371 pin->pio->PIO_SODR = pin->mask;
372}
373
374/**
375 * \brief Sets a low output level on all the PIOs defined in the given Pin instance.
376 * This has no immediate effects on PIOs that are not output, but the PIO
377 * controller will memorize the value they are changed to outputs.
378 *
379 * \param pin Pointer to a Pin instance describing one or more pins.
380 */
381void PIO_Clear(const Pin *pin)
382{
383 pin->pio->PIO_CODR = pin->mask;
384}
385
386/**
387 * \brief Returns 1 if one or more PIO of the given Pin instance currently have
388 * a high level; otherwise returns 0. This method returns the actual value that
389 * is being read on the pin. To return the supposed output value of a pin, use
390 * PIO_GetOutputDataStatus() instead.
391 *
392 * \param pin Pointer to a Pin instance describing one or more pins.
393 *
394 * \return 1 if the Pin instance contains at least one PIO that currently has
395 * a high level; otherwise 0.
396 */
397unsigned char PIO_Get( const Pin *pin )
398{
399 unsigned int reg ;
400
401 if ( (pin->type == PIO_OUTPUT_0) || (pin->type == PIO_OUTPUT_1) )
402 {
403 reg = pin->pio->PIO_ODSR ;
404 }
405 else
406 {
407 reg = pin->pio->PIO_PDSR ;
408 }
409
410 if ( (reg & pin->mask) == 0 )
411 {
412 return 0 ;
413 }
414 else
415 {
416 return 1 ;
417 }
418}
419
420/**
421 * \brief Returns 1 if one or more PIO of the given Pin are configured to output a
422 * high level (even if they are not output).
423 * To get the actual value of the pin, use PIO_Get() instead.
424 *
425 * \param pin Pointer to a Pin instance describing one or more pins.
426 *
427 * \return 1 if the Pin instance contains at least one PIO that is configured
428 * to output a high level; otherwise 0.
429 */
430unsigned char PIO_GetOutputDataStatus(const Pin *pin)
431{
432 if ((pin->pio->PIO_ODSR & pin->mask) == 0) {
433
434 return 0;
435 }
436 else {
437
438 return 1;
439 }
440}
441
442/*
443 * \brief Configures Glitch or Debouncing filter for input.
444 *
445 * \param pin Pointer to a Pin instance describing one or more pins.
446 * \param cuttoff Cutt off frequency for debounce filter.
447 */
448void PIO_SetDebounceFilter( const Pin *pin, uint32_t cuttoff )
449{
450 Pio *pio = pin->pio;
451
452 pio->PIO_IFSCER = pin->mask; /* set Debouncing, 0 bit field no effect */
453 pio->PIO_SCDR = ((32678/(2*(cuttoff))) - 1) & 0x3FFF; /* the lowest 14 bits work */
454}