00001 /* ---------------------------------------------------------------------------- */ 00002 /* Atmel Microcontroller Software Support */ 00003 /* SAM Software Package License */ 00004 /* ---------------------------------------------------------------------------- */ 00005 /* Copyright (c) 2015, Atmel Corporation */ 00006 /* */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without */ 00010 /* modification, are permitted provided that the following condition is met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, */ 00013 /* this list of conditions and the disclaimer below. */ 00014 /* */ 00015 /* Atmel's name may not be used to endorse or promote products derived from */ 00016 /* this software without specific prior written permission. */ 00017 /* */ 00018 /* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */ 00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ 00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */ 00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, */ 00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ 00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */ 00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ 00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ 00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */ 00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00028 /* ---------------------------------------------------------------------------- */ 00029 00030 /** \file */ 00031 00032 /*---------------------------------------------------------------------------- 00033 * Headers 00034 *----------------------------------------------------------------------------*/ 00035 #include "chip.h" 00036 00037 /*---------------------------------------------------------------------------- 00038 * Local functions 00039 *----------------------------------------------------------------------------*/ 00040 00041 /** 00042 * \brief Configures one or more pin(s) of a PIO controller as being controlled by 00043 * peripheral A. Optionally, the corresponding internal pull-up(s) can be enabled. 00044 * 00045 * \param pio Pointer to a PIO controller. 00046 * \param mask Bitmask of one or more pin(s) to configure. 00047 * \param enablePullUp Indicates if the pin(s) internal pull-up shall be 00048 * configured. 00049 */ 00050 static void PIO_SetPeripheralA( 00051 Pio *pio, 00052 unsigned int mask, 00053 unsigned char enablePullUp) 00054 { 00055 unsigned int abcdsr; 00056 /* Disable interrupts on the pin(s) */ 00057 pio->PIO_IDR = mask; 00058 00059 /* Enable the pull-up(s) if necessary */ 00060 if (enablePullUp) 00061 pio->PIO_PUER = mask; 00062 else 00063 pio->PIO_PUDR = mask; 00064 00065 abcdsr = pio->PIO_ABCDSR[0]; 00066 pio->PIO_ABCDSR[0] &= (~mask & abcdsr); 00067 abcdsr = pio->PIO_ABCDSR[1]; 00068 pio->PIO_ABCDSR[1] &= (~mask & abcdsr); 00069 pio->PIO_PDR = mask; 00070 } 00071 00072 /** 00073 * \brief Configures one or more pin(s) of a PIO controller as being controlled 00074 * by peripheral B. Optionally, the corresponding internal pull-up(s) can be 00075 * enabled. 00076 * 00077 * \param pio Pointer to a PIO controller. 00078 * \param mask Bitmask of one or more pin(s) to configure. 00079 * \param enablePullUp Indicates if the pin(s) internal pull-up shall be 00080 * configured. 00081 */ 00082 static void PIO_SetPeripheralB( 00083 Pio *pio, 00084 unsigned int mask, 00085 unsigned char enablePullUp) 00086 { 00087 unsigned int abcdsr; 00088 /* Disable interrupts on the pin(s) */ 00089 pio->PIO_IDR = mask; 00090 00091 /* Enable the pull-up(s) if necessary */ 00092 if (enablePullUp) 00093 pio->PIO_PUER = mask; 00094 else 00095 pio->PIO_PUDR = mask; 00096 00097 abcdsr = pio->PIO_ABCDSR[0]; 00098 pio->PIO_ABCDSR[0] = (mask | abcdsr); 00099 abcdsr = pio->PIO_ABCDSR[1]; 00100 pio->PIO_ABCDSR[1] &= (~mask & abcdsr); 00101 00102 pio->PIO_PDR = mask; 00103 } 00104 00105 /** 00106 * \brief Configures one or more pin(s) of a PIO controller as being controlled 00107 * by peripheral C. Optionally, the corresponding internal pull-up(s) can be 00108 * enabled. 00109 * 00110 * \param pio Pointer to a PIO controller. 00111 * \param mask Bitmask of one or more pin(s) to configure. 00112 * \param enablePullUp Indicates if the pin(s) internal pull-up shall be 00113 * configured. 00114 */ 00115 static void PIO_SetPeripheralC( 00116 Pio *pio, 00117 unsigned int mask, 00118 unsigned char enablePullUp) 00119 { 00120 unsigned int abcdsr; 00121 /* Disable interrupts on the pin(s) */ 00122 pio->PIO_IDR = mask; 00123 00124 /* Enable the pull-up(s) if necessary */ 00125 if (enablePullUp) 00126 pio->PIO_PUER = mask; 00127 else 00128 pio->PIO_PUDR = mask; 00129 00130 abcdsr = pio->PIO_ABCDSR[0]; 00131 pio->PIO_ABCDSR[0] &= (~mask & abcdsr); 00132 abcdsr = pio->PIO_ABCDSR[1]; 00133 pio->PIO_ABCDSR[1] = (mask | abcdsr); 00134 00135 pio->PIO_PDR = mask; 00136 } 00137 00138 /** 00139 * \brief Configures one or more pin(s) of a PIO controller as being controlled 00140 * by peripheral D. Optionally, the corresponding internal pull-up(s) can be 00141 * enabled. 00142 * 00143 * \param pio Pointer to a PIO controller. 00144 * \param mask Bitmask of one or more pin(s) to configure. 00145 * \param enablePullUp Indicates if the pin(s) internal pull-up shall be 00146 * configured. 00147 */ 00148 static void PIO_SetPeripheralD( 00149 Pio *pio, 00150 unsigned int mask, 00151 unsigned char enablePullUp) 00152 { 00153 unsigned int abcdsr; 00154 /* Disable interrupts on the pin(s) */ 00155 pio->PIO_IDR = mask; 00156 00157 /* Enable the pull-up(s) if necessary */ 00158 if (enablePullUp) 00159 pio->PIO_PUER = mask; 00160 else 00161 pio->PIO_PUDR = mask; 00162 00163 abcdsr = pio->PIO_ABCDSR[0]; 00164 pio->PIO_ABCDSR[0] = (mask | abcdsr); 00165 abcdsr = pio->PIO_ABCDSR[1]; 00166 pio->PIO_ABCDSR[1] = (mask | abcdsr); 00167 00168 pio->PIO_PDR = mask; 00169 } 00170 00171 /** 00172 * \brief Configures one or more pin(s) or a PIO controller as inputs. Optionally, 00173 * the corresponding internal pull-up(s) and glitch filter(s) can be enabled. 00174 * 00175 * \param pio Pointer to a PIO controller. 00176 * \param mask Bitmask indicating which pin(s) to configure as input(s). 00177 * \param enablePullUp Indicates if the internal pull-up(s) must be enabled. 00178 * \param enableFilter Indicates if the glitch filter(s) must be enabled. 00179 */ 00180 static void PIO_SetInput( 00181 Pio *pio, 00182 unsigned int mask, 00183 unsigned char attribute) 00184 { 00185 /* Disable interrupts */ 00186 pio->PIO_IDR = mask; 00187 00188 /* Enable pull-up(s) if necessary */ 00189 if (attribute & PIO_PULLUP) 00190 pio->PIO_PUER = mask; 00191 else 00192 pio->PIO_PUDR = mask; 00193 00194 /* Enable Input Filter if necessary */ 00195 if (attribute & (PIO_DEGLITCH | PIO_DEBOUNCE)) 00196 pio->PIO_IFER = mask; 00197 else 00198 pio->PIO_IFDR = mask; 00199 00200 /* Enable de-glitch or de-bounce if necessary */ 00201 if (attribute & PIO_DEGLITCH) 00202 pio->PIO_IFSCDR = mask; 00203 else { 00204 if (attribute & PIO_DEBOUNCE) 00205 pio->PIO_IFSCER = mask; 00206 } 00207 00208 /* Configure pin as input */ 00209 pio->PIO_ODR = mask; 00210 pio->PIO_PER = mask; 00211 } 00212 00213 /** 00214 * \brief Configures one or more pin(s) of a PIO controller as outputs, with the 00215 * given default value. Optionally, the multi-drive feature can be enabled 00216 * on the pin(s). 00217 * 00218 * \param pio Pointer to a PIO controller. 00219 * \param mask Bitmask indicating which pin(s) to configure. 00220 * \param defaultValue Default level on the pin(s). 00221 * \param enableMultiDrive Indicates if the pin(s) shall be configured as 00222 * open-drain. 00223 * \param enablePullUp Indicates if the pin shall have its pull-up activated. 00224 */ 00225 static void PIO_SetOutput( 00226 Pio *pio, 00227 unsigned int mask, 00228 unsigned char defaultValue, 00229 unsigned char enableMultiDrive, 00230 unsigned char enablePullUp) 00231 { 00232 /* Disable interrupts */ 00233 pio->PIO_IDR = mask; 00234 00235 /* Enable pull-up(s) if necessary */ 00236 if (enablePullUp) 00237 pio->PIO_PUER = mask; 00238 else 00239 pio->PIO_PUDR = mask; 00240 00241 /* Enable multi-drive if necessary */ 00242 if (enableMultiDrive) 00243 pio->PIO_MDER = mask; 00244 else 00245 pio->PIO_MDDR = mask; 00246 00247 /* Set default value */ 00248 if (defaultValue) 00249 pio->PIO_SODR = mask; 00250 else 00251 pio->PIO_CODR = mask; 00252 00253 /* Configure pin(s) as output(s) */ 00254 pio->PIO_OER = mask; 00255 pio->PIO_PER = mask; 00256 } 00257 00258 /*---------------------------------------------------------------------------- 00259 * Global functions 00260 *----------------------------------------------------------------------------*/ 00261 00262 /** 00263 * \brief Configures a list of Pin instances, each of which can either hold a 00264 * single pin or a group of pins, depending on the mask value; all pins are 00265 * configured by this function. The size of the array must also be provided and 00266 * is easily computed using PIO_LISTSIZE whenever its length is not known in 00267 * advance. 00268 * 00269 * \param list Pointer to a list of Pin instances. 00270 * \param size Size of the Pin list (calculated using PIO_LISTSIZE). 00271 * 00272 * \return 1 if the pins have been configured properly; otherwise 0. 00273 */ 00274 uint8_t PIO_Configure(const Pin *list, uint32_t size) 00275 { 00276 /* Configure pins */ 00277 while (size > 0) { 00278 switch (list->type) { 00279 case PIO_PERIPH_A: 00280 PIO_SetPeripheralA(list->pio, 00281 list->mask, 00282 (list->attribute & PIO_PULLUP) ? 1 : 0); 00283 break; 00284 00285 case PIO_PERIPH_B: 00286 PIO_SetPeripheralB(list->pio, 00287 list->mask, 00288 (list->attribute & PIO_PULLUP) ? 1 : 0); 00289 break; 00290 00291 case PIO_PERIPH_C: 00292 PIO_SetPeripheralC(list->pio, 00293 list->mask, 00294 (list->attribute & PIO_PULLUP) ? 1 : 0); 00295 break; 00296 00297 case PIO_PERIPH_D: 00298 PIO_SetPeripheralD(list->pio, 00299 list->mask, 00300 (list->attribute & PIO_PULLUP) ? 1 : 0); 00301 break; 00302 00303 case PIO_INPUT: 00304 #ifndef __FPGA 00305 PMC_EnablePeripheral(list->id); 00306 #endif 00307 PIO_SetInput(list->pio, 00308 list->mask, 00309 list->attribute); 00310 break; 00311 00312 case PIO_OUTPUT_0: 00313 case PIO_OUTPUT_1: 00314 PIO_SetOutput(list->pio, 00315 list->mask, 00316 (list->type == PIO_OUTPUT_1), 00317 (list->attribute & PIO_OPENDRAIN) ? 1 : 0, 00318 (list->attribute & PIO_PULLUP) ? 1 : 0); 00319 break; 00320 00321 default: return 0; 00322 } 00323 00324 list++; 00325 size--; 00326 } 00327 00328 return 1; 00329 } 00330 00331 /** 00332 * \brief Sets a high output level on all the PIOs defined in the given Pin 00333 * instance. 00334 * This has no immediate effects on PIOs that are not output, but the PIO 00335 * controller will memorize the value they are changed to outputs. 00336 * 00337 * \param pin Pointer to a Pin instance describing one or more pins. 00338 */ 00339 void PIO_Set(const Pin *pin) 00340 { 00341 pin->pio->PIO_SODR = pin->mask; 00342 } 00343 00344 /** 00345 * \brief Sets a low output level on all the PIOs defined in the given Pin 00346 * instance. 00347 * This has no immediate effects on PIOs that are not output, but the PIO 00348 * controller will memorize the value they are changed to outputs. 00349 * 00350 * \param pin Pointer to a Pin instance describing one or more pins. 00351 */ 00352 void PIO_Clear(const Pin *pin) 00353 { 00354 pin->pio->PIO_CODR = pin->mask; 00355 } 00356 00357 /** 00358 * \brief Returns 1 if one or more PIO of the given Pin instance currently have 00359 * a high level; otherwise returns 0. This method returns the actual value that 00360 * is being read on the pin. To return the supposed output value of a pin, use 00361 * PIO_GetOutputDataStatus() instead. 00362 * 00363 * \param pin Pointer to a Pin instance describing one or more pins. 00364 * 00365 * \return 1 if the Pin instance contains at least one PIO that currently has 00366 * a high level; otherwise 0. 00367 */ 00368 unsigned char PIO_Get(const Pin *pin) 00369 { 00370 unsigned int reg; 00371 00372 if ((pin->type == PIO_OUTPUT_0) || (pin->type == PIO_OUTPUT_1)) 00373 reg = pin->pio->PIO_ODSR; 00374 else 00375 reg = pin->pio->PIO_PDSR; 00376 00377 if ((reg & pin->mask) == 0) 00378 return 0; 00379 else 00380 return 1; 00381 } 00382 00383 /** 00384 * \brief Returns 1 if one or more PIO of the given Pin are configured to output 00385 * a high level (even if they are not output). 00386 * To get the actual value of the pin, use PIO_Get() instead. 00387 * 00388 * \param pin Pointer to a Pin instance describing one or more pins. 00389 * 00390 * \return 1 if the Pin instance contains at least one PIO that is configured 00391 * to output a high level; otherwise 0. 00392 */ 00393 unsigned char PIO_GetOutputDataStatus(const Pin *pin) 00394 { 00395 if ((pin->pio->PIO_ODSR & pin->mask) == 0) 00396 return 0; 00397 else 00398 return 1; 00399 } 00400 00401 /** 00402 * \brief Configures Glitch or Denouncing filter for input. 00403 * 00404 * \param pin Pointer to a Pin instance describing one or more pins. 00405 * \param cuttoff Cut off frequency for denounce filter. 00406 */ 00407 void PIO_SetDebounceFilter(const Pin *pin, uint32_t cuttoff) 00408 { 00409 Pio *pio = pin->pio; 00410 00411 pio->PIO_IFSCER = pin->mask; /* set Denouncing, 0 bit field no effect */ 00412 pio->PIO_SCDR = ((32678 / (2 * (cuttoff))) - 1) & 0x3FFF; 00413 /* the lowest 14 bits work */ 00414 } 00415 00416 /** 00417 * \brief Enable write protect. 00418 * 00419 * \param pin Pointer to a Pin instance describing one or more pins. 00420 */ 00421 void PIO_EnableWriteProtect(const Pin *pin) 00422 { 00423 Pio *pio = pin->pio; 00424 00425 pio->PIO_WPMR = (PIO_WPMR_WPKEY_VALID | PIO_WPMR_WPEN_EN); 00426 } 00427 00428 /** 00429 * \brief Disable write protect. 00430 * 00431 * \param pin Pointer to a Pin instance describing one or more pins. 00432 */ 00433 00434 void PIO_DisableWriteProtect(const Pin *pin) 00435 { 00436 Pio *pio = pin->pio; 00437 00438 pio->PIO_WPMR = (PIO_WPMR_WPKEY_VALID | PIO_WPMR_WPEN_DIS); 00439 } 00440 00441 /** 00442 * \brief Get write protect violation information. 00443 * 00444 * \param pin Pointer to a Pin instance describing one or more pins. 00445 */ 00446 uint32_t PIO_GetWriteProtectViolationInfo(const Pin *pin) 00447 { 00448 Pio *pio = pin->pio; 00449 return (pio->PIO_WPSR); 00450 } 00451 00452 /** 00453 * \brief Set pin type 00454 * the pin is controlled by the corresponding peripheral (A, B, C, D,E) 00455 * \param pin Pointer to a Pin instance describing one or more pins. 00456 * \param pinType PIO_PERIPH_A, PIO_PERIPH_B, ... 00457 */ 00458 void PIO_SetPinType(Pin *pin, uint8_t pinType) 00459 { 00460 pin->type = pinType; 00461 } 00462