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