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