xref: /btstack/port/samv71-xplained-atwilc3000/ASF/sam/drivers/pio/pio.c (revision 1b2596b5303dd8caeea8565532c93cca8dab8cc4)
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