1 /**
2 * \file
3 *
4 * \brief Parallel Input/Output (PIO) Controller driver for SAM.
5 *
6 * Copyright (c) 2011-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47 #include "pio.h"
48
49 #ifndef PIO_WPMR_WPKEY_PASSWD
50 # define PIO_WPMR_WPKEY_PASSWD PIO_WPMR_WPKEY(0x50494Fu)
51 #endif
52
53 /**
54 * \defgroup sam_drivers_pio_group Peripheral Parallel Input/Output (PIO) Controller
55 *
56 * \par Purpose
57 *
58 * The Parallel Input/Output Controller (PIO) manages up to 32 fully
59 * programmable input/output lines. Each I/O line may be dedicated as a
60 * general-purpose I/O or be assigned to a function of an embedded peripheral.
61 * This assures effective optimization of the pins of a product.
62 *
63 * @{
64 */
65
66 #ifndef FREQ_SLOW_CLOCK_EXT
67 /* External slow clock frequency (hz) */
68 #define FREQ_SLOW_CLOCK_EXT 32768
69 #endif
70
71 /**
72 * \brief Configure PIO internal pull-up.
73 *
74 * \param p_pio Pointer to a PIO instance.
75 * \param ul_mask Bitmask of one or more pin(s) to configure.
76 * \param ul_pull_up_enable Indicates if the pin(s) internal pull-up shall be
77 * configured.
78 */
pio_pull_up(Pio * p_pio,const uint32_t ul_mask,const uint32_t ul_pull_up_enable)79 void pio_pull_up(Pio *p_pio, const uint32_t ul_mask,
80 const uint32_t ul_pull_up_enable)
81 {
82 /* Enable the pull-up(s) if necessary */
83 if (ul_pull_up_enable) {
84 p_pio->PIO_PUER = ul_mask;
85 } else {
86 p_pio->PIO_PUDR = ul_mask;
87 }
88 }
89
90 /**
91 * \brief Configure Glitch or Debouncing filter for the specified input(s).
92 *
93 * \param p_pio Pointer to a PIO instance.
94 * \param ul_mask Bitmask of one or more pin(s) to configure.
95 * \param ul_cut_off Cuts off frequency for debouncing filter.
96 */
pio_set_debounce_filter(Pio * p_pio,const uint32_t ul_mask,const uint32_t ul_cut_off)97 void pio_set_debounce_filter(Pio *p_pio, const uint32_t ul_mask,
98 const uint32_t ul_cut_off)
99 {
100 #if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM || SAMV71 || SAMV70 || SAME70 || SAMS70)
101 /* Set Debouncing, 0 bit field no effect */
102 p_pio->PIO_IFSCER = ul_mask;
103 #elif (SAM3XA || SAM3U)
104 /* Set Debouncing, 0 bit field no effect */
105 p_pio->PIO_DIFSR = ul_mask;
106 #else
107 #error "Unsupported device"
108 #endif
109
110 /*
111 * The debouncing filter can filter a pulse of less than 1/2 Period of a
112 * programmable Divided Slow Clock:
113 * Tdiv_slclk = ((DIV+1)*2).Tslow_clock
114 */
115 p_pio->PIO_SCDR = PIO_SCDR_DIV((FREQ_SLOW_CLOCK_EXT /
116 (2 * (ul_cut_off))) - 1);
117 }
118
119 /**
120 * \brief Set a high output level on all the PIOs defined in ul_mask.
121 * This has no immediate effects on PIOs that are not output, but the PIO
122 * controller will save the value if they are changed to outputs.
123 *
124 * \param p_pio Pointer to a PIO instance.
125 * \param ul_mask Bitmask of one or more pin(s) to configure.
126 */
pio_set(Pio * p_pio,const uint32_t ul_mask)127 void pio_set(Pio *p_pio, const uint32_t ul_mask)
128 {
129 p_pio->PIO_SODR = ul_mask;
130 }
131
132 /**
133 * \brief Set a low output level on all the PIOs defined in ul_mask.
134 * This has no immediate effects on PIOs that are not output, but the PIO
135 * controller will save the value if they are changed to outputs.
136 *
137 * \param p_pio Pointer to a PIO instance.
138 * \param ul_mask Bitmask of one or more pin(s) to configure.
139 */
pio_clear(Pio * p_pio,const uint32_t ul_mask)140 void pio_clear(Pio *p_pio, const uint32_t ul_mask)
141 {
142 p_pio->PIO_CODR = ul_mask;
143 }
144
145 /**
146 * \brief Return 1 if one or more PIOs of the given Pin instance currently have
147 * a high level; otherwise returns 0. This method returns the actual value that
148 * is being read on the pin. To return the supposed output value of a pin, use
149 * pio_get_output_data_status() instead.
150 *
151 * \param p_pio Pointer to a PIO instance.
152 * \param ul_type PIO type.
153 * \param ul_mask Bitmask of one or more pin(s) to configure.
154 *
155 * \retval 1 at least one PIO currently has a high level.
156 * \retval 0 all PIOs have a low level.
157 */
pio_get(Pio * p_pio,const pio_type_t ul_type,const uint32_t ul_mask)158 uint32_t pio_get(Pio *p_pio, const pio_type_t ul_type,
159 const uint32_t ul_mask)
160 {
161 uint32_t ul_reg;
162
163 if ((ul_type == PIO_OUTPUT_0) || (ul_type == PIO_OUTPUT_1)) {
164 ul_reg = p_pio->PIO_ODSR;
165 } else {
166 ul_reg = p_pio->PIO_PDSR;
167 }
168
169 if ((ul_reg & ul_mask) == 0) {
170 return 0;
171 } else {
172 return 1;
173 }
174 }
175
176 /**
177 * \brief Configure IO of a PIO controller as being controlled by a specific
178 * peripheral.
179 *
180 * \param p_pio Pointer to a PIO instance.
181 * \param ul_type PIO type.
182 * \param ul_mask Bitmask of one or more pin(s) to configure.
183 */
pio_set_peripheral(Pio * p_pio,const pio_type_t ul_type,const uint32_t ul_mask)184 void pio_set_peripheral(Pio *p_pio, const pio_type_t ul_type,
185 const uint32_t ul_mask)
186 {
187 uint32_t ul_sr;
188
189 /* Disable interrupts on the pin(s) */
190 p_pio->PIO_IDR = ul_mask;
191
192 #if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM || SAMV71 || SAMV70 || SAME70 || SAMS70)
193 switch (ul_type) {
194 case PIO_PERIPH_A:
195 ul_sr = p_pio->PIO_ABCDSR[0];
196 p_pio->PIO_ABCDSR[0] &= (~ul_mask & ul_sr);
197
198 ul_sr = p_pio->PIO_ABCDSR[1];
199 p_pio->PIO_ABCDSR[1] &= (~ul_mask & ul_sr);
200 break;
201 case PIO_PERIPH_B:
202 ul_sr = p_pio->PIO_ABCDSR[0];
203 p_pio->PIO_ABCDSR[0] = (ul_mask | ul_sr);
204
205 ul_sr = p_pio->PIO_ABCDSR[1];
206 p_pio->PIO_ABCDSR[1] &= (~ul_mask & ul_sr);
207 break;
208 #if (!SAMG)
209 case PIO_PERIPH_C:
210 ul_sr = p_pio->PIO_ABCDSR[0];
211 p_pio->PIO_ABCDSR[0] &= (~ul_mask & ul_sr);
212
213 ul_sr = p_pio->PIO_ABCDSR[1];
214 p_pio->PIO_ABCDSR[1] = (ul_mask | ul_sr);
215 break;
216 case PIO_PERIPH_D:
217 ul_sr = p_pio->PIO_ABCDSR[0];
218 p_pio->PIO_ABCDSR[0] = (ul_mask | ul_sr);
219
220 ul_sr = p_pio->PIO_ABCDSR[1];
221 p_pio->PIO_ABCDSR[1] = (ul_mask | ul_sr);
222 break;
223 #endif
224 /* Other types are invalid in this function */
225 case PIO_INPUT:
226 case PIO_OUTPUT_0:
227 case PIO_OUTPUT_1:
228 case PIO_NOT_A_PIN:
229 return;
230 }
231 #elif (SAM3XA|| SAM3U)
232 switch (ul_type) {
233 case PIO_PERIPH_A:
234 ul_sr = p_pio->PIO_ABSR;
235 p_pio->PIO_ABSR &= (~ul_mask & ul_sr);
236 break;
237
238 case PIO_PERIPH_B:
239 ul_sr = p_pio->PIO_ABSR;
240 p_pio->PIO_ABSR = (ul_mask | ul_sr);
241 break;
242
243 // other types are invalid in this function
244 case PIO_INPUT:
245 case PIO_OUTPUT_0:
246 case PIO_OUTPUT_1:
247 case PIO_NOT_A_PIN:
248 return;
249 }
250 #else
251 #error "Unsupported device"
252 #endif
253
254 /* Remove the pins from under the control of PIO */
255 p_pio->PIO_PDR = ul_mask;
256 }
257
258 /**
259 * \brief Configure one or more pin(s) or a PIO controller as inputs.
260 * Optionally, the corresponding internal pull-up(s) and glitch filter(s) can
261 * be enabled.
262 *
263 * \param p_pio Pointer to a PIO instance.
264 * \param ul_mask Bitmask indicating which pin(s) to configure as input(s).
265 * \param ul_attribute PIO attribute(s).
266 */
pio_set_input(Pio * p_pio,const uint32_t ul_mask,const uint32_t ul_attribute)267 void pio_set_input(Pio *p_pio, const uint32_t ul_mask,
268 const uint32_t ul_attribute)
269 {
270 pio_disable_interrupt(p_pio, ul_mask);
271 pio_pull_up(p_pio, ul_mask, ul_attribute & PIO_PULLUP);
272
273 /* Enable Input Filter if necessary */
274 if (ul_attribute & (PIO_DEGLITCH | PIO_DEBOUNCE)) {
275 p_pio->PIO_IFER = ul_mask;
276 } else {
277 p_pio->PIO_IFDR = ul_mask;
278 }
279
280 #if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM || SAMV71 || SAMV70 || SAME70 || SAMS70)
281 /* Enable de-glitch or de-bounce if necessary */
282 if (ul_attribute & PIO_DEGLITCH) {
283 p_pio->PIO_IFSCDR = ul_mask;
284 } else {
285 if (ul_attribute & PIO_DEBOUNCE) {
286 p_pio->PIO_IFSCER = ul_mask;
287 }
288 }
289 #elif (SAM3XA|| SAM3U)
290 /* Enable de-glitch or de-bounce if necessary */
291 if (ul_attribute & PIO_DEGLITCH) {
292 p_pio->PIO_SCIFSR = ul_mask;
293 } else {
294 if (ul_attribute & PIO_DEBOUNCE) {
295 p_pio->PIO_DIFSR = ul_mask;
296 }
297 }
298 #else
299 #error "Unsupported device"
300 #endif
301
302 /* Configure pin as input */
303 p_pio->PIO_ODR = ul_mask;
304 p_pio->PIO_PER = ul_mask;
305 }
306
307 /**
308 * \brief Configure one or more pin(s) of a PIO controller as outputs, with
309 * the given default value. Optionally, the multi-drive feature can be enabled
310 * on the pin(s).
311 *
312 * \param p_pio Pointer to a PIO instance.
313 * \param ul_mask Bitmask indicating which pin(s) to configure.
314 * \param ul_default_level Default level on the pin(s).
315 * \param ul_multidrive_enable Indicates if the pin(s) shall be configured as
316 * open-drain.
317 * \param ul_pull_up_enable Indicates if the pin shall have its pull-up
318 * activated.
319 */
pio_set_output(Pio * p_pio,const uint32_t ul_mask,const uint32_t ul_default_level,const uint32_t ul_multidrive_enable,const uint32_t ul_pull_up_enable)320 void pio_set_output(Pio *p_pio, const uint32_t ul_mask,
321 const uint32_t ul_default_level,
322 const uint32_t ul_multidrive_enable,
323 const uint32_t ul_pull_up_enable)
324 {
325 pio_disable_interrupt(p_pio, ul_mask);
326 pio_pull_up(p_pio, ul_mask, ul_pull_up_enable);
327
328 /* Enable multi-drive if necessary */
329 if (ul_multidrive_enable) {
330 p_pio->PIO_MDER = ul_mask;
331 } else {
332 p_pio->PIO_MDDR = ul_mask;
333 }
334
335 /* Set default value */
336 if (ul_default_level) {
337 p_pio->PIO_SODR = ul_mask;
338 } else {
339 p_pio->PIO_CODR = ul_mask;
340 }
341
342 /* Configure pin(s) as output(s) */
343 p_pio->PIO_OER = ul_mask;
344 p_pio->PIO_PER = ul_mask;
345 }
346
347 /**
348 * \brief Perform complete pin(s) configuration; general attributes and PIO init
349 * if necessary.
350 *
351 * \param p_pio Pointer to a PIO instance.
352 * \param ul_type PIO type.
353 * \param ul_mask Bitmask of one or more pin(s) to configure.
354 * \param ul_attribute Pins attributes.
355 *
356 * \return Whether the pin(s) have been configured properly.
357 */
pio_configure(Pio * p_pio,const pio_type_t ul_type,const uint32_t ul_mask,const uint32_t ul_attribute)358 uint32_t pio_configure(Pio *p_pio, const pio_type_t ul_type,
359 const uint32_t ul_mask, const uint32_t ul_attribute)
360 {
361 /* Configure pins */
362 switch (ul_type) {
363 case PIO_PERIPH_A:
364 case PIO_PERIPH_B:
365 #if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAM4CP || SAM4CM || SAMV71 || SAMV70 || SAME70 || SAMS70)
366 case PIO_PERIPH_C:
367 case PIO_PERIPH_D:
368 #endif
369 pio_set_peripheral(p_pio, ul_type, ul_mask);
370 pio_pull_up(p_pio, ul_mask, (ul_attribute & PIO_PULLUP));
371 break;
372
373 case PIO_INPUT:
374 pio_set_input(p_pio, ul_mask, ul_attribute);
375 break;
376
377 case PIO_OUTPUT_0:
378 case PIO_OUTPUT_1:
379 pio_set_output(p_pio, ul_mask, (ul_type == PIO_OUTPUT_1),
380 (ul_attribute & PIO_OPENDRAIN) ? 1 : 0,
381 (ul_attribute & PIO_PULLUP) ? 1 : 0);
382 break;
383
384 default:
385 return 0;
386 }
387
388 return 1;
389 }
390
391 /**
392 * \brief Return 1 if one or more PIOs of the given Pin are configured to
393 * output a high level (even if they are not output).
394 * To get the actual value of the pin, use PIO_Get() instead.
395 *
396 * \param p_pio Pointer to a PIO instance.
397 * \param ul_mask Bitmask of one or more pin(s).
398 *
399 * \retval 1 At least one PIO is configured to output a high level.
400 * \retval 0 All PIOs are configured to output a low level.
401 */
pio_get_output_data_status(const Pio * p_pio,const uint32_t ul_mask)402 uint32_t pio_get_output_data_status(const Pio *p_pio,
403 const uint32_t ul_mask)
404 {
405 if ((p_pio->PIO_ODSR & ul_mask) == 0) {
406 return 0;
407 } else {
408 return 1;
409 }
410 }
411
412 /**
413 * \brief Configure PIO pin multi-driver.
414 *
415 * \param p_pio Pointer to a PIO instance.
416 * \param ul_mask Bitmask of one or more pin(s) to configure.
417 * \param ul_multi_driver_enable Indicates if the pin(s) multi-driver shall be
418 * configured.
419 */
pio_set_multi_driver(Pio * p_pio,const uint32_t ul_mask,const uint32_t ul_multi_driver_enable)420 void pio_set_multi_driver(Pio *p_pio, const uint32_t ul_mask,
421 const uint32_t ul_multi_driver_enable)
422 {
423 /* Enable the multi-driver if necessary */
424 if (ul_multi_driver_enable) {
425 p_pio->PIO_MDER = ul_mask;
426 } else {
427 p_pio->PIO_MDDR = ul_mask;
428 }
429 }
430
431 /**
432 * \brief Get multi-driver status.
433 *
434 * \param p_pio Pointer to a PIO instance.
435 *
436 * \return The multi-driver mask value.
437 */
pio_get_multi_driver_status(const Pio * p_pio)438 uint32_t pio_get_multi_driver_status(const Pio *p_pio)
439 {
440 return p_pio->PIO_MDSR;
441 }
442
443
444 #if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM || SAMV71 || SAMV70 || SAME70 || SAMS70)
445 /**
446 * \brief Configure PIO pin internal pull-down.
447 *
448 * \param p_pio Pointer to a PIO instance.
449 * \param ul_mask Bitmask of one or more pin(s) to configure.
450 * \param ul_pull_down_enable Indicates if the pin(s) internal pull-down shall
451 * be configured.
452 */
pio_pull_down(Pio * p_pio,const uint32_t ul_mask,const uint32_t ul_pull_down_enable)453 void pio_pull_down(Pio *p_pio, const uint32_t ul_mask,
454 const uint32_t ul_pull_down_enable)
455 {
456 /* Enable the pull-down if necessary */
457 if (ul_pull_down_enable) {
458 p_pio->PIO_PPDER = ul_mask;
459 } else {
460 p_pio->PIO_PPDDR = ul_mask;
461 }
462 }
463 #endif
464
465 /**
466 * \brief Enable PIO output write for synchronous data output.
467 *
468 * \param p_pio Pointer to a PIO instance.
469 * \param ul_mask Bitmask of one or more pin(s) to configure.
470 */
pio_enable_output_write(Pio * p_pio,const uint32_t ul_mask)471 void pio_enable_output_write(Pio *p_pio, const uint32_t ul_mask)
472 {
473 p_pio->PIO_OWER = ul_mask;
474 }
475
476 /**
477 * \brief Disable PIO output write.
478 *
479 * \param p_pio Pointer to a PIO instance.
480 * \param ul_mask Bitmask of one or more pin(s) to configure.
481 */
pio_disable_output_write(Pio * p_pio,const uint32_t ul_mask)482 void pio_disable_output_write(Pio *p_pio, const uint32_t ul_mask)
483 {
484 p_pio->PIO_OWDR = ul_mask;
485 }
486
487 /**
488 * \brief Read PIO output write status.
489 *
490 * \param p_pio Pointer to a PIO instance.
491 *
492 * \return The output write mask value.
493 */
pio_get_output_write_status(const Pio * p_pio)494 uint32_t pio_get_output_write_status(const Pio *p_pio)
495 {
496 return p_pio->PIO_OWSR;
497 }
498
499 /**
500 * \brief Synchronously write on output pins.
501 * \note Only bits unmasked by PIO_OWSR (Output Write Status Register) are
502 * written.
503 *
504 * \param p_pio Pointer to a PIO instance.
505 * \param ul_mask Bitmask of one or more pin(s) to configure.
506 */
pio_sync_output_write(Pio * p_pio,const uint32_t ul_mask)507 void pio_sync_output_write(Pio *p_pio, const uint32_t ul_mask)
508 {
509 p_pio->PIO_ODSR = ul_mask;
510 }
511
512 #if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM || SAMV71 || SAMV70 || SAME70 || SAMS70)
513 /**
514 * \brief Configure PIO pin schmitt trigger. By default the Schmitt trigger is
515 * active.
516 * Disabling the Schmitt Trigger is requested when using the QTouch Library.
517 *
518 * \param p_pio Pointer to a PIO instance.
519 * \param ul_mask Bitmask of one or more pin(s) to configure.
520 */
pio_set_schmitt_trigger(Pio * p_pio,const uint32_t ul_mask)521 void pio_set_schmitt_trigger(Pio *p_pio, const uint32_t ul_mask)
522 {
523 p_pio->PIO_SCHMITT = ul_mask;
524 }
525
526 /**
527 * \brief Get PIO pin schmitt trigger status.
528 *
529 * \param p_pio Pointer to a PIO instance.
530 *
531 * \return The schmitt trigger mask value.
532 */
pio_get_schmitt_trigger(const Pio * p_pio)533 uint32_t pio_get_schmitt_trigger(const Pio *p_pio)
534 {
535 return p_pio->PIO_SCHMITT;
536 }
537 #endif
538
539 /**
540 * \brief Configure the given interrupt source.
541 * Interrupt can be configured to trigger on rising edge, falling edge,
542 * high level, low level or simply on level change.
543 *
544 * \param p_pio Pointer to a PIO instance.
545 * \param ul_mask Interrupt source bit map.
546 * \param ul_attr Interrupt source attributes.
547 */
pio_configure_interrupt(Pio * p_pio,const uint32_t ul_mask,const uint32_t ul_attr)548 void pio_configure_interrupt(Pio *p_pio, const uint32_t ul_mask,
549 const uint32_t ul_attr)
550 {
551 /* Configure additional interrupt mode registers. */
552 if (ul_attr & PIO_IT_AIME) {
553 /* Enable additional interrupt mode. */
554 p_pio->PIO_AIMER = ul_mask;
555
556 /* If bit field of the selected pin is 1, set as
557 Rising Edge/High level detection event. */
558 if (ul_attr & PIO_IT_RE_OR_HL) {
559 /* Rising Edge or High Level */
560 p_pio->PIO_REHLSR = ul_mask;
561 } else {
562 /* Falling Edge or Low Level */
563 p_pio->PIO_FELLSR = ul_mask;
564 }
565
566 /* If bit field of the selected pin is 1, set as
567 edge detection source. */
568 if (ul_attr & PIO_IT_EDGE) {
569 /* Edge select */
570 p_pio->PIO_ESR = ul_mask;
571 } else {
572 /* Level select */
573 p_pio->PIO_LSR = ul_mask;
574 }
575 } else {
576 /* Disable additional interrupt mode. */
577 p_pio->PIO_AIMDR = ul_mask;
578 }
579 }
580
581 /**
582 * \brief Enable the given interrupt source.
583 * The PIO must be configured as an NVIC interrupt source as well.
584 * The status register of the corresponding PIO controller is cleared
585 * prior to enabling the interrupt.
586 *
587 * \param p_pio Pointer to a PIO instance.
588 * \param ul_mask Interrupt sources bit map.
589 */
pio_enable_interrupt(Pio * p_pio,const uint32_t ul_mask)590 void pio_enable_interrupt(Pio *p_pio, const uint32_t ul_mask)
591 {
592 p_pio->PIO_ISR;
593 p_pio->PIO_IER = ul_mask;
594 }
595
596 /**
597 * \brief Disable a given interrupt source, with no added side effects.
598 *
599 * \param p_pio Pointer to a PIO instance.
600 * \param ul_mask Interrupt sources bit map.
601 */
pio_disable_interrupt(Pio * p_pio,const uint32_t ul_mask)602 void pio_disable_interrupt(Pio *p_pio, const uint32_t ul_mask)
603 {
604 p_pio->PIO_IDR = ul_mask;
605 }
606
607 /**
608 * \brief Read PIO interrupt status.
609 *
610 * \param p_pio Pointer to a PIO instance.
611 *
612 * \return The interrupt status mask value.
613 */
pio_get_interrupt_status(const Pio * p_pio)614 uint32_t pio_get_interrupt_status(const Pio *p_pio)
615 {
616 return p_pio->PIO_ISR;
617 }
618
619 /**
620 * \brief Read PIO interrupt mask.
621 *
622 * \param p_pio Pointer to a PIO instance.
623 *
624 * \return The interrupt mask value.
625 */
pio_get_interrupt_mask(const Pio * p_pio)626 uint32_t pio_get_interrupt_mask(const Pio *p_pio)
627 {
628 return p_pio->PIO_IMR;
629 }
630
631 /**
632 * \brief Set additional interrupt mode.
633 *
634 * \param p_pio Pointer to a PIO instance.
635 * \param ul_mask Interrupt sources bit map.
636 * \param ul_attribute Pin(s) attributes.
637 */
pio_set_additional_interrupt_mode(Pio * p_pio,const uint32_t ul_mask,const uint32_t ul_attribute)638 void pio_set_additional_interrupt_mode(Pio *p_pio,
639 const uint32_t ul_mask, const uint32_t ul_attribute)
640 {
641 /* Enables additional interrupt mode if needed */
642 if (ul_attribute & PIO_IT_AIME) {
643 /* Enables additional interrupt mode */
644 p_pio->PIO_AIMER = ul_mask;
645
646 /* Configures the Polarity of the event detection */
647 /* (Rising/Falling Edge or High/Low Level) */
648 if (ul_attribute & PIO_IT_RE_OR_HL) {
649 /* Rising Edge or High Level */
650 p_pio->PIO_REHLSR = ul_mask;
651 } else {
652 /* Falling Edge or Low Level */
653 p_pio->PIO_FELLSR = ul_mask;
654 }
655
656 /* Configures the type of event detection (Edge or Level) */
657 if (ul_attribute & PIO_IT_EDGE) {
658 /* Edge select */
659 p_pio->PIO_ESR = ul_mask;
660 } else {
661 /* Level select */
662 p_pio->PIO_LSR = ul_mask;
663 }
664 } else {
665 /* Disable additional interrupt mode */
666 p_pio->PIO_AIMDR = ul_mask;
667 }
668 }
669
670 #ifndef PIO_WPMR_WPKEY_PASSWD
671 #define PIO_WPMR_WPKEY_PASSWD PIO_WPMR_WPKEY(0x50494FU)
672 #endif
673
674 /**
675 * \brief Enable or disable write protect of PIO registers.
676 *
677 * \param p_pio Pointer to a PIO instance.
678 * \param ul_enable 1 to enable, 0 to disable.
679 */
pio_set_writeprotect(Pio * p_pio,const uint32_t ul_enable)680 void pio_set_writeprotect(Pio *p_pio, const uint32_t ul_enable)
681 {
682 p_pio->PIO_WPMR = PIO_WPMR_WPKEY_PASSWD | (ul_enable & PIO_WPMR_WPEN);
683 }
684
685 /**
686 * \brief Read write protect status.
687 *
688 * \param p_pio Pointer to a PIO instance.
689 *
690 * \return Return write protect status.
691 */
pio_get_writeprotect_status(const Pio * p_pio)692 uint32_t pio_get_writeprotect_status(const Pio *p_pio)
693 {
694 return p_pio->PIO_WPSR;
695 }
696
697 /**
698 * \brief Return the value of a pin.
699 *
700 * \param ul_pin The pin number.
701 *
702 * \return The pin value.
703 *
704 * \note If pin is output: a pull-up or pull-down could hide the actual value.
705 * The function \ref pio_get can be called to get the actual pin output
706 * level.
707 * \note If pin is input: PIOx must be clocked to sample the signal.
708 * See PMC driver.
709 */
pio_get_pin_value(uint32_t ul_pin)710 uint32_t pio_get_pin_value(uint32_t ul_pin)
711 {
712 Pio *p_pio = pio_get_pin_group(ul_pin);
713
714 return (p_pio->PIO_PDSR >> (ul_pin & 0x1F)) & 1;
715 }
716
717 /**
718 * \brief Drive a GPIO pin to 1.
719 *
720 * \param ul_pin The pin index.
721 *
722 * \note The function \ref pio_configure_pin must be called beforehand.
723 */
pio_set_pin_high(uint32_t ul_pin)724 void pio_set_pin_high(uint32_t ul_pin)
725 {
726 Pio *p_pio = pio_get_pin_group(ul_pin);
727
728 /* Value to be driven on the I/O line: 1. */
729 p_pio->PIO_SODR = 1 << (ul_pin & 0x1F);
730 }
731
732 /**
733 * \brief Drive a GPIO pin to 0.
734 *
735 * \param ul_pin The pin index.
736 *
737 * \note The function \ref pio_configure_pin must be called before.
738 */
pio_set_pin_low(uint32_t ul_pin)739 void pio_set_pin_low(uint32_t ul_pin)
740 {
741 Pio *p_pio = pio_get_pin_group(ul_pin);
742
743 /* Value to be driven on the I/O line: 0. */
744 p_pio->PIO_CODR = 1 << (ul_pin & 0x1F);
745 }
746
747 /**
748 * \brief Toggle a GPIO pin.
749 *
750 * \param ul_pin The pin index.
751 *
752 * \note The function \ref pio_configure_pin must be called before.
753 */
pio_toggle_pin(uint32_t ul_pin)754 void pio_toggle_pin(uint32_t ul_pin)
755 {
756 Pio *p_pio = pio_get_pin_group(ul_pin);
757
758 if (p_pio->PIO_ODSR & (1 << (ul_pin & 0x1F))) {
759 /* Value to be driven on the I/O line: 0. */
760 p_pio->PIO_CODR = 1 << (ul_pin & 0x1F);
761 } else {
762 /* Value to be driven on the I/O line: 1. */
763 p_pio->PIO_SODR = 1 << (ul_pin & 0x1F);
764 }
765 }
766
767 /**
768 * \brief Perform complete pin(s) configuration; general attributes and PIO init
769 * if necessary.
770 *
771 * \param ul_pin Bitmask of one or more pin(s) to configure.
772 * \param ul_flags Pins attributes.
773 *
774 * \return Whether the pin(s) have been configured properly.
775 */
pio_configure_pin(uint32_t ul_pin,const uint32_t ul_flags)776 uint32_t pio_configure_pin(uint32_t ul_pin, const uint32_t ul_flags)
777 {
778 Pio *p_pio = pio_get_pin_group(ul_pin);
779
780 /* Configure pins */
781 switch (ul_flags & PIO_TYPE_Msk) {
782 case PIO_TYPE_PIO_PERIPH_A:
783 pio_set_peripheral(p_pio, PIO_PERIPH_A, (1 << (ul_pin & 0x1F)));
784 pio_pull_up(p_pio, (1 << (ul_pin & 0x1F)),
785 (ul_flags & PIO_PULLUP));
786 break;
787 case PIO_TYPE_PIO_PERIPH_B:
788 pio_set_peripheral(p_pio, PIO_PERIPH_B, (1 << (ul_pin & 0x1F)));
789 pio_pull_up(p_pio, (1 << (ul_pin & 0x1F)),
790 (ul_flags & PIO_PULLUP));
791 break;
792 #if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAM4CP || SAM4CM || SAMV71 || SAMV70 || SAME70 || SAMS70)
793 case PIO_TYPE_PIO_PERIPH_C:
794 pio_set_peripheral(p_pio, PIO_PERIPH_C, (1 << (ul_pin & 0x1F)));
795 pio_pull_up(p_pio, (1 << (ul_pin & 0x1F)),
796 (ul_flags & PIO_PULLUP));
797 break;
798 case PIO_TYPE_PIO_PERIPH_D:
799 pio_set_peripheral(p_pio, PIO_PERIPH_D, (1 << (ul_pin & 0x1F)));
800 pio_pull_up(p_pio, (1 << (ul_pin & 0x1F)),
801 (ul_flags & PIO_PULLUP));
802 break;
803 #endif
804
805 case PIO_TYPE_PIO_INPUT:
806 pio_set_input(p_pio, (1 << (ul_pin & 0x1F)), ul_flags);
807 break;
808
809 case PIO_TYPE_PIO_OUTPUT_0:
810 case PIO_TYPE_PIO_OUTPUT_1:
811 pio_set_output(p_pio, (1 << (ul_pin & 0x1F)),
812 ((ul_flags & PIO_TYPE_PIO_OUTPUT_1)
813 == PIO_TYPE_PIO_OUTPUT_1) ? 1 : 0,
814 (ul_flags & PIO_OPENDRAIN) ? 1 : 0,
815 (ul_flags & PIO_PULLUP) ? 1 : 0);
816 break;
817
818 default:
819 return 0;
820 }
821
822 return 1;
823 }
824
825 /**
826 * \brief Drive a GPIO port to 1.
827 *
828 * \param p_pio Base address of the PIO port.
829 * \param ul_mask Bitmask of one or more pin(s) to toggle.
830 */
pio_set_pin_group_high(Pio * p_pio,uint32_t ul_mask)831 void pio_set_pin_group_high(Pio *p_pio, uint32_t ul_mask)
832 {
833 /* Value to be driven on the I/O line: 1. */
834 p_pio->PIO_SODR = ul_mask;
835 }
836
837 /**
838 * \brief Drive a GPIO port to 0.
839 *
840 * \param p_pio Base address of the PIO port.
841 * \param ul_mask Bitmask of one or more pin(s) to toggle.
842 */
pio_set_pin_group_low(Pio * p_pio,uint32_t ul_mask)843 void pio_set_pin_group_low(Pio *p_pio, uint32_t ul_mask)
844 {
845 /* Value to be driven on the I/O line: 0. */
846 p_pio->PIO_CODR = ul_mask;
847 }
848
849 /**
850 * \brief Toggle a GPIO group.
851 *
852 * \param p_pio Pointer to a PIO instance.
853 * \param ul_mask Bitmask of one or more pin(s) to configure.
854 */
pio_toggle_pin_group(Pio * p_pio,uint32_t ul_mask)855 void pio_toggle_pin_group(Pio *p_pio, uint32_t ul_mask)
856 {
857 if (p_pio->PIO_ODSR & ul_mask) {
858 /* Value to be driven on the I/O line: 0. */
859 p_pio->PIO_CODR = ul_mask;
860 } else {
861 /* Value to be driven on the I/O line: 1. */
862 p_pio->PIO_SODR = ul_mask;
863 }
864 }
865
866 /**
867 * \brief Perform complete pin(s) configuration; general attributes and PIO init
868 * if necessary.
869 *
870 * \param p_pio Pointer to a PIO instance.
871 * \param ul_mask Bitmask of one or more pin(s) to configure.
872 * \param ul_flags Pin(s) attributes.
873 *
874 * \return Whether the pin(s) have been configured properly.
875 */
pio_configure_pin_group(Pio * p_pio,uint32_t ul_mask,const uint32_t ul_flags)876 uint32_t pio_configure_pin_group(Pio *p_pio,
877 uint32_t ul_mask, const uint32_t ul_flags)
878 {
879 /* Configure pins */
880 switch (ul_flags & PIO_TYPE_Msk) {
881 case PIO_TYPE_PIO_PERIPH_A:
882 pio_set_peripheral(p_pio, PIO_PERIPH_A, ul_mask);
883 pio_pull_up(p_pio, ul_mask, (ul_flags & PIO_PULLUP));
884 break;
885 case PIO_TYPE_PIO_PERIPH_B:
886 pio_set_peripheral(p_pio, PIO_PERIPH_B, ul_mask);
887 pio_pull_up(p_pio, ul_mask, (ul_flags & PIO_PULLUP));
888 break;
889 #if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAM4CP || SAM4CM || SAMV71 || SAMV70 || SAME70 || SAMS70)
890 case PIO_TYPE_PIO_PERIPH_C:
891 pio_set_peripheral(p_pio, PIO_PERIPH_C, ul_mask);
892 pio_pull_up(p_pio, ul_mask, (ul_flags & PIO_PULLUP));
893 break;
894 case PIO_TYPE_PIO_PERIPH_D:
895 pio_set_peripheral(p_pio, PIO_PERIPH_D, ul_mask);
896 pio_pull_up(p_pio, ul_mask, (ul_flags & PIO_PULLUP));
897 break;
898 #endif
899
900 case PIO_TYPE_PIO_INPUT:
901 pio_set_input(p_pio, ul_mask, ul_flags);
902 break;
903
904 case PIO_TYPE_PIO_OUTPUT_0:
905 case PIO_TYPE_PIO_OUTPUT_1:
906 pio_set_output(p_pio, ul_mask,
907 ((ul_flags & PIO_TYPE_PIO_OUTPUT_1)
908 == PIO_TYPE_PIO_OUTPUT_1) ? 1 : 0,
909 (ul_flags & PIO_OPENDRAIN) ? 1 : 0,
910 (ul_flags & PIO_PULLUP) ? 1 : 0);
911 break;
912
913 default:
914 return 0;
915 }
916
917 return 1;
918 }
919
920 /**
921 * \brief Enable interrupt for a GPIO pin.
922 *
923 * \param ul_pin The pin index.
924 *
925 * \note The function \ref gpio_configure_pin must be called before.
926 */
pio_enable_pin_interrupt(uint32_t ul_pin)927 void pio_enable_pin_interrupt(uint32_t ul_pin)
928 {
929 Pio *p_pio = pio_get_pin_group(ul_pin);
930
931 p_pio->PIO_IER = 1 << (ul_pin & 0x1F);
932 }
933
934
935 /**
936 * \brief Disable interrupt for a GPIO pin.
937 *
938 * \param ul_pin The pin index.
939 *
940 * \note The function \ref gpio_configure_pin must be called before.
941 */
pio_disable_pin_interrupt(uint32_t ul_pin)942 void pio_disable_pin_interrupt(uint32_t ul_pin)
943 {
944 Pio *p_pio = pio_get_pin_group(ul_pin);
945
946 p_pio->PIO_IDR = 1 << (ul_pin & 0x1F);
947 }
948
949
950 /**
951 * \brief Return GPIO port for a GPIO pin.
952 *
953 * \param ul_pin The pin index.
954 *
955 * \return Pointer to \ref Pio struct for GPIO port.
956 */
pio_get_pin_group(uint32_t ul_pin)957 Pio *pio_get_pin_group(uint32_t ul_pin)
958 {
959 Pio *p_pio;
960
961 #if (SAM4C || SAM4CP)
962 # ifdef ID_PIOD
963 if (ul_pin > PIO_PC9_IDX) {
964 p_pio = PIOD;
965 } else if (ul_pin > PIO_PB31_IDX) {
966 # else
967 if (ul_pin > PIO_PB31_IDX) {
968 # endif
969 p_pio = PIOC;
970 } else {
971 p_pio = (Pio *)((uint32_t)PIOA + (PIO_DELTA * (ul_pin >> 5)));
972 }
973 #elif (SAM4CM)
974 if (ul_pin > PIO_PB21_IDX) {
975 p_pio = PIOC;
976 } else {
977 p_pio = (Pio *)((uint32_t)PIOA + (PIO_DELTA * (ul_pin >> 5)));
978 }
979 #else
980 p_pio = (Pio *)((uint32_t)PIOA + (PIO_DELTA * (ul_pin >> 5)));
981 #endif
982 return p_pio;
983 }
984
985 /**
986 * \brief Return GPIO port peripheral ID for a GPIO pin.
987 *
988 * \param ul_pin The pin index.
989 *
990 * \return GPIO port peripheral ID.
991 */
992 uint32_t pio_get_pin_group_id(uint32_t ul_pin)
993 {
994 uint32_t ul_id;
995
996 #if (SAM4C || SAM4CP)
997 # ifdef ID_PIOD
998 if (ul_pin > PIO_PC9_IDX) {
999 ul_id = ID_PIOD;
1000 } else if (ul_pin > PIO_PB31_IDX) {
1001 # else
1002 if (ul_pin > PIO_PB31_IDX) {
1003 # endif
1004 ul_id = ID_PIOC;
1005 } else {
1006 ul_id = ID_PIOA + (ul_pin >> 5);
1007 }
1008 #elif (SAM4CM)
1009 if (ul_pin > PIO_PB21_IDX) {
1010 ul_id = ID_PIOC;
1011 } else {
1012 ul_id = ID_PIOA + (ul_pin >> 5);
1013 }
1014 #else
1015 ul_id = ID_PIOA + (ul_pin >> 5);
1016 #endif
1017 return ul_id;
1018 }
1019
1020
1021 /**
1022 * \brief Return GPIO port pin mask for a GPIO pin.
1023 *
1024 * \param ul_pin The pin index.
1025 *
1026 * \return GPIO port pin mask.
1027 */
1028 uint32_t pio_get_pin_group_mask(uint32_t ul_pin)
1029 {
1030 uint32_t ul_mask = 1 << (ul_pin & 0x1F);
1031 return ul_mask;
1032 }
1033
1034 #if (SAM3S || SAM4S || SAM4E || SAMV71 || SAMV70 || SAME70 || SAMS70)
1035 /* Capture mode enable flag */
1036 uint32_t pio_capture_enable_flag;
1037
1038 /**
1039 * \brief Configure PIO capture mode.
1040 * \note PIO capture mode will be disabled automatically.
1041 *
1042 * \param p_pio Pointer to a PIO instance.
1043 * \param ul_mode Bitmask of one or more modes.
1044 */
1045 void pio_capture_set_mode(Pio *p_pio, uint32_t ul_mode)
1046 {
1047 ul_mode &= (~PIO_PCMR_PCEN); /* Disable PIO capture mode */
1048 p_pio->PIO_PCMR = ul_mode;
1049 }
1050
1051 /**
1052 * \brief Enable PIO capture mode.
1053 *
1054 * \param p_pio Pointer to a PIO instance.
1055 */
1056 void pio_capture_enable(Pio *p_pio)
1057 {
1058 p_pio->PIO_PCMR |= PIO_PCMR_PCEN;
1059 pio_capture_enable_flag = true;
1060 }
1061
1062 /**
1063 * \brief Disable PIO capture mode.
1064 *
1065 * \param p_pio Pointer to a PIO instance.
1066 */
1067 void pio_capture_disable(Pio *p_pio)
1068 {
1069 p_pio->PIO_PCMR &= (~PIO_PCMR_PCEN);
1070 pio_capture_enable_flag = false;
1071 }
1072
1073 /**
1074 * \brief Read from Capture Reception Holding Register.
1075 * \note Data presence should be tested before any read attempt.
1076 *
1077 * \param p_pio Pointer to a PIO instance.
1078 * \param pul_data Pointer to store the data.
1079 *
1080 * \retval 0 Success.
1081 * \retval 1 I/O Failure, Capture data is not ready.
1082 */
1083 uint32_t pio_capture_read(const Pio *p_pio, uint32_t *pul_data)
1084 {
1085 /* Check if the data is ready */
1086 if ((p_pio->PIO_PCISR & PIO_PCISR_DRDY) == 0) {
1087 return 1;
1088 }
1089
1090 /* Read data */
1091 *pul_data = p_pio->PIO_PCRHR;
1092 return 0;
1093 }
1094
1095 /**
1096 * \brief Enable the given interrupt source of PIO capture. The status
1097 * register of the corresponding PIO capture controller is cleared prior
1098 * to enabling the interrupt.
1099 *
1100 * \param p_pio Pointer to a PIO instance.
1101 * \param ul_mask Interrupt sources bit map.
1102 */
1103 void pio_capture_enable_interrupt(Pio *p_pio, const uint32_t ul_mask)
1104 {
1105 p_pio->PIO_PCISR;
1106 p_pio->PIO_PCIER = ul_mask;
1107 }
1108
1109 /**
1110 * \brief Disable a given interrupt source of PIO capture.
1111 *
1112 * \param p_pio Pointer to a PIO instance.
1113 * \param ul_mask Interrupt sources bit map.
1114 */
1115 void pio_capture_disable_interrupt(Pio *p_pio, const uint32_t ul_mask)
1116 {
1117 p_pio->PIO_PCIDR = ul_mask;
1118 }
1119
1120 /**
1121 * \brief Read PIO interrupt status of PIO capture.
1122 *
1123 * \param p_pio Pointer to a PIO instance.
1124 *
1125 * \return The interrupt status mask value.
1126 */
1127 uint32_t pio_capture_get_interrupt_status(const Pio *p_pio)
1128 {
1129 return p_pio->PIO_PCISR;
1130 }
1131
1132 /**
1133 * \brief Read PIO interrupt mask of PIO capture.
1134 *
1135 * \param p_pio Pointer to a PIO instance.
1136 *
1137 * \return The interrupt mask value.
1138 */
1139 uint32_t pio_capture_get_interrupt_mask(const Pio *p_pio)
1140 {
1141 return p_pio->PIO_PCIMR;
1142 }
1143 #if !(SAMV71 || SAMV70 || SAME70 || SAMS70)
1144 /**
1145 * \brief Get PDC registers base address.
1146 *
1147 * \param p_pio Pointer to an PIO peripheral.
1148 *
1149 * \return PIOA PDC register base address.
1150 */
1151 Pdc *pio_capture_get_pdc_base(const Pio *p_pio)
1152 {
1153 UNUSED(p_pio); /* Stop warning */
1154 return PDC_PIOA;
1155 }
1156 #endif
1157 #endif
1158
1159 #if (SAM4C || SAM4CP || SAM4CM || SAMG55)
1160 /**
1161 * \brief Set PIO IO drive.
1162 *
1163 * \param p_pio Pointer to an PIO peripheral.
1164 * \param ul_line Line index (0..31).
1165 * \param mode IO drive mode.
1166 */
1167 void pio_set_io_drive(Pio *p_pio, uint32_t ul_line,
1168 enum pio_io_drive_mode mode)
1169 {
1170 p_pio->PIO_DRIVER &= ~(1 << ul_line);
1171 p_pio->PIO_DRIVER |= mode << ul_line;
1172 }
1173 #endif
1174
1175 #if (SAMV71 || SAMV70 || SAME70 || SAMS70)
1176 /**
1177 * \brief Enable PIO keypad controller.
1178 *
1179 * \param p_pio Pointer to a PIO instance.
1180 */
1181 void pio_keypad_enable(Pio *p_pio)
1182 {
1183 p_pio->PIO_KER |= PIO_KER_KCE;
1184 }
1185
1186 /**
1187 * \brief Disable PIO keypad controller.
1188 *
1189 * \param p_pio Pointer to a PIO instance.
1190 */
1191 void pio_keypad_disable(Pio *p_pio)
1192 {
1193 p_pio->PIO_KER &= (~PIO_KER_KCE);
1194 }
1195
1196 /**
1197 * \brief Set PIO keypad controller row number.
1198 *
1199 * \param p_pio Pointer to a PIO instance.
1200 * \param num Number of row of the keypad matrix.
1201 */
1202 void pio_keypad_set_row_num(Pio *p_pio, uint8_t num)
1203 {
1204 p_pio->PIO_KRCR &= (~PIO_KRCR_NBR_Msk);
1205 p_pio->PIO_KRCR |= PIO_KRCR_NBR(num);
1206 }
1207
1208 /**
1209 * \brief Get PIO keypad controller row number.
1210 *
1211 * \param p_pio Pointer to a PIO instance.
1212 *
1213 * \return Number of row of the keypad matrix.
1214 */
1215 uint8_t pio_keypad_get_row_num(const Pio *p_pio)
1216 {
1217 return ((p_pio->PIO_KRCR & PIO_KRCR_NBR_Msk) >> PIO_KRCR_NBR_Pos);
1218 }
1219
1220 /**
1221 * \brief Set PIO keypad controller column number.
1222 *
1223 * \param p_pio Pointer to a PIO instance.
1224 * \param num Number of column of the keypad matrix.
1225 */
1226 void pio_keypad_set_column_num(Pio *p_pio, uint8_t num)
1227 {
1228 p_pio->PIO_KRCR &= (~PIO_KRCR_NBC_Msk);
1229 p_pio->PIO_KRCR |= PIO_KRCR_NBC(num);
1230 }
1231
1232 /**
1233 * \brief Get PIO keypad controller column number.
1234 *
1235 * \param p_pio Pointer to a PIO instance.
1236 *
1237 * \return Number of column of the keypad matrix.
1238 */
1239 uint8_t pio_keypad_get_column_num(const Pio *p_pio)
1240 {
1241 return ((p_pio->PIO_KRCR & PIO_KRCR_NBC_Msk) >> PIO_KRCR_NBC_Pos);
1242 }
1243
1244 /**
1245 * \brief Set PIO keypad matrix debouncing value.
1246 *
1247 * \param p_pio Pointer to a PIO instance.
1248 * \param num Number of debouncing value.
1249 */
1250 void pio_keypad_set_debouncing_value(Pio *p_pio, uint16_t value)
1251 {
1252 p_pio->PIO_KDR = PIO_KDR_DBC(value);
1253 }
1254
1255 /**
1256 * \brief Get PIO keypad matrix debouncing value.
1257 *
1258 * \param p_pio Pointer to a PIO instance.
1259 *
1260 * \return The keypad debouncing value.
1261 */
1262 uint16_t pio_keypad_get_debouncing_value(const Pio *p_pio)
1263 {
1264 return ((p_pio->PIO_KDR & PIO_KDR_DBC_Msk) >> PIO_KDR_DBC_Pos);
1265 }
1266
1267 /**
1268 * \brief Enable the interrupt source of PIO keypad.
1269 *
1270 * \param p_pio Pointer to a PIO instance.
1271 * \param ul_mask Interrupt sources bit map.
1272 */
1273 void pio_keypad_enable_interrupt(Pio *p_pio, uint32_t ul_mask)
1274 {
1275 p_pio->PIO_KIER = ul_mask;
1276 }
1277
1278 /**
1279 * \brief Disable the interrupt source of PIO keypad.
1280 *
1281 * \param p_pio Pointer to a PIO instance.
1282 * \param ul_mask Interrupt sources bit map.
1283 */
1284 void pio_keypad_disable_interrupt(Pio *p_pio, uint32_t ul_mask)
1285 {
1286 p_pio->PIO_KIDR = ul_mask;
1287 }
1288
1289 /**
1290 * \brief Get interrupt mask of PIO keypad.
1291 *
1292 * \param p_pio Pointer to a PIO instance.
1293 *
1294 * \return The interrupt mask value.
1295 */
1296 uint32_t pio_keypad_get_interrupt_mask(const Pio *p_pio)
1297 {
1298 return p_pio->PIO_KIMR;
1299 }
1300
1301 /**
1302 * \brief Get key press status of PIO keypad.
1303 *
1304 * \param p_pio Pointer to a PIO instance.
1305 *
1306 * \return The status of key press.
1307 * 0: No key press has been detected.
1308 * 1: At least one key press has been detected.
1309 */
1310 uint32_t pio_keypad_get_press_status(const Pio *p_pio)
1311 {
1312 if (p_pio->PIO_KSR & PIO_KSR_KPR) {
1313 return 1;
1314 } else {
1315 return 0;
1316 }
1317 }
1318
1319 /**
1320 * \brief Get key release status of PIO keypad.
1321 *
1322 * \param p_pio Pointer to a PIO instance.
1323 *
1324 * \return The status of key release.
1325 * 0 No key release has been detected.
1326 * 1 At least one key release has been detected.
1327 */
1328 uint32_t pio_keypad_get_release_status(const Pio *p_pio)
1329 {
1330 if (p_pio->PIO_KSR & PIO_KSR_KRL) {
1331 return 1;
1332 } else {
1333 return 0;
1334 }
1335 }
1336
1337 /**
1338 * \brief Get simultaneous key press number of PIO keypad.
1339 *
1340 * \param p_pio Pointer to a PIO instance.
1341 *
1342 * \return The number of simultaneous key press.
1343 */
1344 uint8_t pio_keypad_get_simult_press_num(const Pio *p_pio)
1345 {
1346 return ((p_pio->PIO_KSR & PIO_KSR_NBKPR_Msk) >> PIO_KSR_NBKPR_Pos);
1347 }
1348
1349 /**
1350 * \brief Get simultaneous key release number of PIO keypad.
1351 *
1352 * \param p_pio Pointer to a PIO instance.
1353 *
1354 * \return The number of simultaneous key release.
1355 */
1356 uint8_t pio_keypad_get_simult_release_num(const Pio *p_pio)
1357 {
1358 return ((p_pio->PIO_KSR & PIO_KSR_NBKRL_Msk) >> PIO_KSR_NBKRL_Pos);
1359 }
1360
1361 /**
1362 * \brief Get detected key press row index of PIO keypad.
1363 *
1364 * \param p_pio Pointer to a PIO instance.
1365 * \param queue The queue of key press row
1366 *
1367 * \return The index of detected key press row.
1368 */
1369 uint8_t pio_keypad_get_press_row_index(const Pio *p_pio, uint8_t queue)
1370 {
1371 switch (queue) {
1372 case 0:
1373 return ((p_pio->PIO_KKPR & PIO_KKPR_KEY0ROW_Msk) >> PIO_KKPR_KEY0ROW_Pos);
1374 case 1:
1375 return ((p_pio->PIO_KKPR & PIO_KKPR_KEY1ROW_Msk) >> PIO_KKPR_KEY1ROW_Pos);
1376 case 2:
1377 return ((p_pio->PIO_KKPR & PIO_KKPR_KEY2ROW_Msk) >> PIO_KKPR_KEY2ROW_Pos);
1378 case 3:
1379 return ((p_pio->PIO_KKPR & PIO_KKPR_KEY3ROW_Msk) >> PIO_KKPR_KEY3ROW_Pos);
1380 default:
1381 return 0;
1382 }
1383 }
1384
1385 /**
1386 * \brief Get detected key press column index of PIO keypad.
1387 *
1388 * \param p_pio Pointer to a PIO instance.
1389 * \param queue The queue of key press column
1390 *
1391 * \return The index of detected key press column.
1392 */
1393 uint8_t pio_keypad_get_press_column_index(const Pio *p_pio, uint8_t queue)
1394 {
1395 switch (queue) {
1396 case 0:
1397 return ((p_pio->PIO_KKPR & PIO_KKPR_KEY0COL_Msk) >> PIO_KKPR_KEY0COL_Pos);
1398 case 1:
1399 return ((p_pio->PIO_KKPR & PIO_KKPR_KEY1COL_Msk) >> PIO_KKPR_KEY1COL_Pos);
1400 case 2:
1401 return ((p_pio->PIO_KKPR & PIO_KKPR_KEY2COL_Msk) >> PIO_KKPR_KEY2COL_Pos);
1402 case 3:
1403 return ((p_pio->PIO_KKPR & PIO_KKPR_KEY3COL_Msk) >> PIO_KKPR_KEY3COL_Pos);
1404 default:
1405 return 0;
1406 }
1407 }
1408
1409 /**
1410 * \brief Get detected key release row index of PIO keypad.
1411 *
1412 * \param p_pio Pointer to a PIO instance.
1413 * \param queue The queue of key release row
1414 *
1415 * \return The index of detected key release row.
1416 */
1417 uint8_t pio_keypad_get_release_row_index(const Pio *p_pio, uint8_t queue)
1418 {
1419 switch (queue) {
1420 case 0:
1421 return ((p_pio->PIO_KKRR & PIO_KKRR_KEY0ROW_Msk) >> PIO_KKRR_KEY0ROW_Pos);
1422 case 1:
1423 return ((p_pio->PIO_KKRR & PIO_KKRR_KEY1ROW_Msk) >> PIO_KKRR_KEY1ROW_Pos);
1424 case 2:
1425 return ((p_pio->PIO_KKRR & PIO_KKRR_KEY2ROW_Msk) >> PIO_KKRR_KEY2ROW_Pos);
1426 case 3:
1427 return ((p_pio->PIO_KKRR & PIO_KKRR_KEY3ROW_Msk) >> PIO_KKRR_KEY3ROW_Pos);
1428 default:
1429 return 0;
1430 }
1431 }
1432
1433 /**
1434 * \brief Get detected key release column index of PIO keypad.
1435 *
1436 * \param p_pio Pointer to a PIO instance.
1437 * \param queue The queue of key release column
1438 *
1439 * \return The index of detected key release column.
1440 */
1441 uint8_t pio_keypad_get_release_column_index(const Pio *p_pio, uint8_t queue)
1442 {
1443 switch (queue) {
1444 case 0:
1445 return ((p_pio->PIO_KKRR & PIO_KKRR_KEY0COL_Msk) >> PIO_KKRR_KEY0COL_Pos);
1446 case 1:
1447 return ((p_pio->PIO_KKRR & PIO_KKRR_KEY1COL_Msk) >> PIO_KKRR_KEY1COL_Pos);
1448 case 2:
1449 return ((p_pio->PIO_KKRR & PIO_KKRR_KEY2COL_Msk) >> PIO_KKRR_KEY2COL_Pos);
1450 case 3:
1451 return ((p_pio->PIO_KKRR & PIO_KKRR_KEY3COL_Msk) >> PIO_KKRR_KEY3COL_Pos);
1452 default:
1453 return 0;
1454 }
1455 }
1456
1457 #endif
1458
1459 //@}
1460
1461