00001 /********************************************************************************* 00002 00003 Copyright 2006-2008 MakingThings 00004 00005 Licensed under the Apache License, 00006 Version 2.0 (the "License"); you may not use this file except in compliance 00007 with the License. You may obtain a copy of the License at 00008 00009 http://www.apache.org/licenses/LICENSE-2.0 00010 00011 Unless required by applicable law or agreed to in writing, software distributed 00012 under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 00013 CONDITIONS OF ANY KIND, either express or implied. See the License for 00014 the specific language governing permissions and limitations under the License. 00015 00016 *********************************************************************************/ 00017 00018 00019 /** \file io.c 00020 Subsystem for manipulating the general purpose IO lines. 00021 */ 00022 00023 /* Library includes */ 00024 00025 00026 /* Scheduler includes */ 00027 00028 /* Hardware specific headers */ 00029 #include "Board.h" 00030 #include "AT91SAM7X256.h" 00031 00032 #include "io.h" 00033 #include "config.h" 00034 00035 /* Local Structures */ 00036 00037 struct IoPin_ 00038 { 00039 uchar users : 7 ; 00040 uchar lock : 1 ; 00041 } __attribute__((packed)); 00042 00043 #define IO_PIN_COUNT 64 00044 #define IO_USERS_MAX 127 00045 00046 typedef struct IoPin_ IoPin ; 00047 00048 struct Io_ 00049 { 00050 int users; 00051 int init; 00052 int portAMask; 00053 int portBMask; 00054 IoPin pins[ IO_PIN_COUNT ]; 00055 } Io; 00056 00057 static void Io_Init( void ); 00058 static void Io_Deinit( void ); 00059 static int Io_SetOutput( int index ); 00060 static int Io_SetInput( int index ); 00061 static int Io_PullupEnable( int index ); 00062 static int Io_PullupDisable( int index ); 00063 static int Io_PioEnable( int index ); 00064 static int Io_PioDisable( int index ); 00065 00066 /** \defgroup Io IO 00067 A mechanism to manage the 64 IO lines on the controller. 00068 00069 The 64 IO (Input/Output) lines on the Make Controller are grouped into 2 ports of 32 lines each, 00070 port A and port B. Each line has many parameters that can be configured: 00071 - whether it's an input or an output 00072 - whether it's turned on or off (if it's an output) 00073 - whether the internal pullup is enabled 00074 - whether the glitch filter is enabled 00075 - and more... 00076 00077 In addition, all IO pins serve at least double and sometimes triple duty, being general IO lines 00078 and also being IO lines for one or more of the controller's many on-chip peripherals, such as the 00079 Ethernet system, USB system, SPI, UART, etc. To help address this, the IO system provides a mechanism to "lock" 00080 the IO lines, so that you can always be sure that your line has not been altered by some other 00081 system while you weren't looking. 00082 00083 \section api IO API 00084 This API can be used in two ways - either one line at a time or many at a time. Functions to set 00085 the values of all the lines at once end in \b Bits. For example, the one-at-a-time 00086 mechanism for setting an IO line configured as an output to true is called Io_SetTrue(). 00087 It takes a single index and the one for setting a number of lines is Io_SetTrueBits( ) which takes a 00088 mask with the values of all the lines. 00089 00090 To find the index to use for a single line, please see \ref IoIndices. For the constants to help 00091 create masks for the \b Bits style, please see \ref IoBits. 00092 00093 \section use Normal Use 00094 The pattern of use is to call Io_Start() prior to using an IO line. If it returns successfully, the 00095 line was not previously locked and you can use it as you please. Otherwise, you don't have access to the 00096 IO line, and should not make any calls to configure or use it. 00097 00098 \todo Add glitch filter control 00099 \ingroup Core 00100 @{ 00101 */ 00102 00103 /** 00104 Get access to an IO line, possibly locking it. 00105 @param index The IO line to start - use the appropriate entry from \ref IoIndices 00106 @param lock Whether to lock this line from being used by another system. 00107 @return 0 on success, < 0 on failure 00108 00109 \b Example 00110 00111 \code 00112 if( Io_Start(IO_PA18, true) == CONTROLLER_OK) 00113 { 00114 // then we have access to PA18 and successfully locked it 00115 } 00116 else 00117 // can't use PA18 00118 \endcode 00119 */ 00120 int Io_Start( int index, bool lock ) 00121 { 00122 if ( index < 0 || index > IO_PIN_COUNT ) 00123 return CONTROLLER_ERROR_ILLEGAL_INDEX; 00124 IoPin* p = &Io.pins[ index ]; 00125 // If it's not locked at all and 00126 // either no lock is requested or no a lock is requested but no other are using the io and 00127 // there are not a huge number of users 00128 if ( !p->lock && ( !lock || ( lock && p->users == 0 ) ) && ( p->users < IO_USERS_MAX - 2 ) ) 00129 { 00130 if ( Io.users == 0 ) 00131 Io_Init(); 00132 00133 // Lock it up. 00134 Io.users++; 00135 p->users++; 00136 if ( lock ) 00137 p->lock = true; 00138 00139 return CONTROLLER_OK; 00140 } 00141 else 00142 return CONTROLLER_ERROR_TOO_MANY_USERS; 00143 } 00144 00145 /** 00146 Release your lock on an IO line, possibly deactivating it. 00147 When you call Io_Stop(), it will remove the lock you placed on the line. If no other 00148 systems are using it, the line will be deactivated. 00149 @param index The IO line to stop - use the appropriate entry from \ref IoIndices 00150 @return 0 on success, < 0 on failure 00151 00152 \b Example 00153 00154 \code 00155 Io_Stop(IO_PA18); 00156 \endcode 00157 */ 00158 int Io_Stop( int index ) 00159 { 00160 if ( index < 0 || index > IO_PIN_COUNT ) 00161 return CONTROLLER_ERROR_ILLEGAL_INDEX; 00162 IoPin* p = &Io.pins[ index ]; 00163 if ( p->users > 0 ) 00164 { 00165 Io.users--; 00166 p->users--; 00167 p->lock = false; 00168 00169 if ( Io.users == 0 ) 00170 Io_Deinit(); 00171 00172 return CONTROLLER_OK; 00173 } 00174 else 00175 return CONTROLLER_ERROR_TOO_MANY_STOPS; 00176 } 00177 00178 int Io_StartBits( longlong bits, bool lock ) 00179 { 00180 IoPin* p = &Io.pins[ 0 ]; 00181 int i = 0; 00182 int failure = -1; 00183 ullong mask = 1LL; 00184 for ( i = 0; i < 64; i++ ) 00185 { 00186 if ( bits & mask ) 00187 { 00188 if ( !p->lock && ( !lock || ( lock && p->users == 0 ) ) && p->users < IO_USERS_MAX - 2 ) 00189 { 00190 if ( Io.users == 0 ) 00191 Io_Init(); 00192 if ( lock ) 00193 p->lock = true; 00194 p->users++; 00195 Io.users++; 00196 } 00197 else 00198 { 00199 failure = i; 00200 break; 00201 } 00202 } 00203 mask <<= 1; 00204 p++; 00205 } 00206 00207 if ( failure != -1 ) 00208 { 00209 IoPin* p = &Io.pins[ 0 ]; 00210 mask = 1LL; 00211 for ( i = 0; i < failure; i++ ) 00212 { 00213 if ( bits & mask ) 00214 { 00215 if ( lock ) 00216 p->lock = false; 00217 p->users--; 00218 Io.users--; 00219 if ( Io.users == 0 ) 00220 Io_Deinit(); 00221 } 00222 mask <<= 1; 00223 p++; 00224 } 00225 return CONTROLLER_ERROR_CANT_LOCK; 00226 } 00227 00228 return CONTROLLER_OK; 00229 } 00230 00231 int Io_StopBits( longlong bits ) 00232 { 00233 IoPin* p = &Io.pins[ 0 ]; 00234 int i = 0; 00235 ullong mask = 1LL; 00236 for ( i = 0; i < 64; i++ ) 00237 { 00238 if ( bits & mask ) 00239 { 00240 p->lock = false; 00241 p->users--; 00242 Io.users--; 00243 00244 if ( Io.users == 0 ) 00245 Io_Deinit(); 00246 } 00247 mask <<= 1; 00248 p++; 00249 } 00250 return CONTROLLER_OK; 00251 } 00252 00253 /** 00254 Read whether an IO pin is in use. 00255 @param index An int specifying which IO line. Use the appropriate entry from the \ref IoIndices 00256 @return non-zero if active, 0 if inactive 00257 00258 \b Example 00259 \code 00260 if( Io_GetActive( IO_PA23 ) ) 00261 { 00262 // it's already active 00263 } 00264 else 00265 { 00266 // not yet active 00267 } 00268 \endcode 00269 */ 00270 bool Io_GetActive( int index ) 00271 { 00272 if ( index < 0 || index > IO_PIN_COUNT ) 00273 return CONTROLLER_ERROR_ILLEGAL_INDEX; 00274 IoPin* p = &Io.pins[ index ]; 00275 return p->users > 0; 00276 } 00277 00278 /** 00279 Set whether an IO line is an output or an input. 00280 Use the IO_INPUT and IO_OUTPUT symbols to avoid confusion. 00281 @param index An int specifying which IO line. Use the appropriate entry from the \ref IoIndices 00282 @param output Specify 1 for an output, or 0 for an input. 00283 @return CONTROLLER_OK (0) on success, non-zero otherwise. 00284 00285 \b Example 00286 \code 00287 // Set io23 to an input 00288 if( Io_SetDirection( IO_PA23, IO_INPUT ) == CONTROLLER_OK ) 00289 { 00290 // success 00291 } 00292 \endcode 00293 */ 00294 int Io_SetDirection( int index, bool output ) 00295 { 00296 if ( output ) 00297 return Io_SetOutput( index ); 00298 else 00299 return Io_SetInput( index ); 00300 } 00301 00302 /** 00303 Read whether an IO line is an output or an input. 00304 @param index An int specifying which IO line. Use the appropriate entry from the \ref IoIndices 00305 @return Non-zero if the pin is an output, 0 if it's an input. 00306 00307 \b Example 00308 \code 00309 // Check whether IO 23 is an output or input 00310 if( Io_GetDirection( IO_PA23 ) ) 00311 { 00312 // then we're an output 00313 } 00314 else 00315 { 00316 // we're an input 00317 } 00318 \endcode 00319 */ 00320 bool Io_GetDirection( int index ) 00321 { 00322 if ( index < 0 || index > IO_PIN_COUNT ) 00323 return CONTROLLER_ERROR_ILLEGAL_INDEX; 00324 00325 if ( index < 32 ) 00326 return ( AT91C_BASE_PIOA->PIO_OSR & ( 1 << index ) ) != 0; 00327 else 00328 return ( AT91C_BASE_PIOB->PIO_OSR & ( 1 << ( index & 0x1F ) ) ) != 0; 00329 } 00330 00331 // static 00332 int Io_SetOutput( int index ) 00333 { 00334 if ( index < 0 || index > IO_PIN_COUNT ) 00335 return CONTROLLER_ERROR_ILLEGAL_INDEX; 00336 00337 // Switch to outputs 00338 if ( index < 32 ) 00339 AT91C_BASE_PIOA->PIO_OER = 1 << index; 00340 else 00341 AT91C_BASE_PIOB->PIO_OER = 1 << ( index & 0x1F ); 00342 00343 return CONTROLLER_OK; 00344 } 00345 00346 // static 00347 int Io_SetInput( int index ) 00348 { 00349 if ( index < 0 || index > IO_PIN_COUNT ) 00350 return CONTROLLER_ERROR_ILLEGAL_INDEX; 00351 00352 // Switch to inputs 00353 if ( index < 32 ) 00354 AT91C_BASE_PIOA->PIO_ODR = 1 << index; 00355 else 00356 AT91C_BASE_PIOB->PIO_ODR = 1 << ( index & 0x1F ); 00357 00358 return CONTROLLER_OK; 00359 } 00360 00361 /** 00362 Turn an IO line on or off. 00363 This IO should have already been set to be an output via Io_SetDirection( ) 00364 @param index An int specifying which IO line. Use the appropriate entry from the \ref IoIndices 00365 @param value Non-zero for on, 0 for off. 00366 @return CONTROLLER_OK (0) on success, otherwise non-zero. 00367 00368 \b Example 00369 \code 00370 // Turn on IO 17 00371 Io_SetValue( IO_PA17, 1 ); 00372 \endcode 00373 */ 00374 int Io_SetValue( int index, bool value ) 00375 { 00376 if ( index < 0 || index > IO_PIN_COUNT ) 00377 return CONTROLLER_ERROR_ILLEGAL_INDEX; 00378 00379 // Switch to outputs 00380 int mask = 1 << ( index & 0x1F ); 00381 if ( index < 32 ) 00382 { 00383 if ( value ) 00384 AT91C_BASE_PIOA->PIO_SODR = mask; 00385 else 00386 AT91C_BASE_PIOA->PIO_CODR = mask; 00387 } 00388 else 00389 { 00390 if ( value ) 00391 AT91C_BASE_PIOB->PIO_SODR = mask; 00392 else 00393 AT91C_BASE_PIOB->PIO_CODR = mask; 00394 } 00395 00396 return CONTROLLER_OK; 00397 } 00398 00399 /** 00400 Read whether an IO line, presumably set as an output, is on or off. 00401 @param index An int specifying which IO line. Use the appropriate entry from the \ref IoIndices 00402 @return CONTROLLER_OK (0) on success, otherwise non-zero. 00403 00404 \b Example 00405 \code 00406 // Turn on IO 17 00407 Io_SetValue( IO_PA17, 1 ); 00408 \endcode 00409 */ 00410 bool Io_GetValue( int index ) 00411 { 00412 if ( index < 0 || index > IO_PIN_COUNT ) 00413 return 0; 00414 int mask = 1 << ( index & 0x1F ); 00415 if ( index < 32 ) 00416 return ( ( AT91C_BASE_PIOA->PIO_PDSR & mask ) != 0 ) ? 1 : 0; 00417 else 00418 return ( ( AT91C_BASE_PIOB->PIO_PDSR & mask ) != 0 ) ? 1 : 0; 00419 } 00420 00421 /** 00422 Configure an IO line to be part of its peripheral A. 00423 @param index An int specifying which IO line. Use the appropriate entry from the \ref IoIndices 00424 @return 0 on success, non-zero on failure 00425 00426 \b Example 00427 \code 00428 Io_SetPeripheralA( IO_PA18); 00429 \endcode 00430 */ 00431 int Io_SetPeripheralA( int index ) 00432 { 00433 if ( index < 0 || index > IO_PIN_COUNT ) 00434 return CONTROLLER_ERROR_ILLEGAL_INDEX; 00435 00436 int mask = 1 << ( index & 0x1F ); 00437 if ( index < 32 ) 00438 AT91C_BASE_PIOA->PIO_ASR = mask; 00439 else 00440 AT91C_BASE_PIOB->PIO_ASR = mask; 00441 00442 return CONTROLLER_OK; 00443 } 00444 00445 /** 00446 Configure an IO line to be part of its peripheral B. 00447 @param index An int specifying which IO line. Use the appropriate entry from the \ref IoIndices 00448 @return 0 on success, non-zero on failure 00449 00450 \b Example 00451 \code 00452 Io_SetPeripheralB( IO_PA18); 00453 \endcode 00454 */ 00455 int Io_SetPeripheralB( int index ) 00456 { 00457 if ( index < 0 || index > IO_PIN_COUNT ) 00458 return CONTROLLER_ERROR_ILLEGAL_INDEX; 00459 00460 int mask = 1 << ( index & 0x1F ); 00461 if ( index < 32 ) 00462 AT91C_BASE_PIOA->PIO_BSR = mask; 00463 else 00464 AT91C_BASE_PIOB->PIO_BSR = mask; 00465 00466 return CONTROLLER_OK; 00467 } 00468 00469 /** 00470 Configure an IO line to be a general purpose IO. 00471 @param index An int specifying which IO line. Use the appropriate entry from the \ref IoIndices 00472 @param enable Whether to enable a pin as a PIO or disable it, reverting to an unconfigured state. 00473 @return 0 on success, non-zero on failure 00474 00475 \b Example 00476 \code 00477 Io_SetPio( IO_PA18); 00478 \endcode 00479 */ 00480 int Io_SetPio( int index, bool enable ) 00481 { 00482 if ( enable ) 00483 return Io_PioEnable( index ); 00484 else 00485 return Io_PioDisable( index ); 00486 } 00487 00488 /** 00489 Read whether an IO line is configured as a general purpose IO. 00490 @param index An int specifying which IO line. Use the appropriate entry from the \ref IoIndices 00491 @return true if it is a PIO, false if it's not. 00492 00493 \b Example 00494 \code 00495 if( Io_GetPio( IO_PA18) ) 00496 { 00497 // then we know PA18 is a PIO 00498 } 00499 \endcode 00500 */ 00501 bool Io_GetPio( int index ) 00502 { 00503 if ( index < 0 || index > IO_PIN_COUNT ) 00504 return CONTROLLER_ERROR_ILLEGAL_INDEX; 00505 00506 if ( index < 32 ) 00507 return ( AT91C_BASE_PIOA->PIO_PSR & ( 1 << index ) ) != 0; 00508 else 00509 return ( AT91C_BASE_PIOB->PIO_PSR & ( 1 << ( index & 0x1F ) ) ) != 0; 00510 } 00511 00512 // static 00513 int Io_PioEnable( int index ) 00514 { 00515 if ( index < 0 || index > IO_PIN_COUNT ) 00516 return CONTROLLER_ERROR_ILLEGAL_INDEX; 00517 00518 int mask = 1 << ( index & 0x1F ); 00519 if ( index < 32 ) 00520 AT91C_BASE_PIOA->PIO_PER = mask; 00521 else 00522 AT91C_BASE_PIOB->PIO_PER = mask; 00523 00524 return CONTROLLER_OK; 00525 } 00526 00527 // static 00528 int Io_PioDisable( int index ) 00529 { 00530 if ( index < 0 || index > IO_PIN_COUNT ) 00531 return CONTROLLER_ERROR_ILLEGAL_INDEX; 00532 00533 int mask = 1 << ( index & 0x1F ); 00534 if ( index < 32 ) 00535 AT91C_BASE_PIOA->PIO_PDR = mask; 00536 else 00537 AT91C_BASE_PIOB->PIO_PDR = mask; 00538 00539 return CONTROLLER_OK; 00540 } 00541 00542 /** 00543 Set the pullup resistor for an IO line on or off. 00544 @param index An int specifying which IO line. Use the appropriate entry from the \ref IoIndices 00545 @param enable Non-zero for on, 0 for off. 00546 @return CONTROLLER_OK (0) on success, otherwise non-zero. 00547 00548 \b Example 00549 \code 00550 // Turn on the pullup for IO 17 00551 Io_SetPullup( IO_PA17, 1 ); 00552 \endcode 00553 */ 00554 int Io_SetPullup( int index, bool enable ) 00555 { 00556 if ( enable ) 00557 return Io_PullupEnable( index ); 00558 else 00559 return Io_PullupDisable( index ); 00560 } 00561 00562 /** 00563 Read whether the pullup resistor for an IO line on or off. 00564 @param index An int specifying which IO line. Use the appropriate entry from the \ref IoIndices 00565 @return CONTROLLER_OK (0) on success, otherwise non-zero. 00566 00567 \b Example 00568 \code 00569 // Turn on the pullup for IO 17 00570 Io_GetPullup( IO_PA17 ); 00571 \endcode 00572 */ 00573 bool Io_GetPullup( int index ) 00574 { 00575 if ( index < 0 || index > IO_PIN_COUNT ) 00576 return CONTROLLER_ERROR_ILLEGAL_INDEX; 00577 00578 // The PullUp status register is inverted. 00579 if ( index < 32 ) 00580 return ( AT91C_BASE_PIOA->PIO_PPUSR & ( 1 << index ) ) == 0; 00581 else 00582 return ( AT91C_BASE_PIOB->PIO_PPUSR & ( 1 << ( index & 0x1F ) ) ) == 0; 00583 } 00584 00585 // static 00586 int Io_PullupEnable( int index ) 00587 { 00588 if ( index < 0 || index > IO_PIN_COUNT ) 00589 return CONTROLLER_ERROR_ILLEGAL_INDEX; 00590 00591 int mask = 1 << ( index & 0x1F ); 00592 if ( index < 32 ) 00593 AT91C_BASE_PIOA->PIO_PPUER = mask; 00594 else 00595 AT91C_BASE_PIOB->PIO_PPUER = mask; 00596 00597 return CONTROLLER_OK; 00598 } 00599 00600 // static 00601 int Io_PullupDisable( int index ) 00602 { 00603 if ( index < 0 || index > IO_PIN_COUNT ) 00604 return CONTROLLER_ERROR_ILLEGAL_INDEX; 00605 00606 int mask = 1 << ( index & 0x1F ); 00607 if ( index < 32 ) 00608 AT91C_BASE_PIOA->PIO_PPUDR = mask; 00609 else 00610 AT91C_BASE_PIOB->PIO_PPUDR = mask; 00611 00612 return CONTROLLER_OK; 00613 } 00614 00615 /* 00616 Enable/disable IO pullups by the batch. 00617 @param bits The bitmask containing the IO lines you'd like to configure - see \ref IoBits. Must be 00618 a longlong to accommodate all 64 bits. 00619 @param enable true to enable, false to disable the pullup 00620 00621 \b Example 00622 \code 00623 longlong mymask = 0; 00624 mymask |= (IO_PA18_BIT | IO_PA00_BIT | IO_PB12_BIT ); 00625 Io_SetPullupBits( mymask, enable ); // enable those pullups 00626 \endcode 00627 */ 00628 void Io_SetPullupBits( longlong bits, bool enable ) 00629 { 00630 if(enable) 00631 { 00632 AT91C_BASE_PIOB->PIO_PPUER = bits >> 32; 00633 AT91C_BASE_PIOA->PIO_PPUER = bits & 0xFFFFFFFF; 00634 } 00635 else 00636 { 00637 AT91C_BASE_PIOB->PIO_PPUDR = bits >> 32; 00638 AT91C_BASE_PIOA->PIO_PPUDR = bits & 0xFFFFFFFF; 00639 } 00640 } 00641 00642 /** 00643 Set the values of a batch of IO lines at once. 00644 @param bits The bitmask containing the IO lines you'd like to configure - see \ref IoBits. Must be 00645 a longlong to accommodate all 64 bits. 00646 @param values The mask of 0 or non-0 values that you'd like to write into those lines. 00647 */ 00648 void Io_SetValueBits( longlong bits, longlong values ) 00649 { 00650 int aBits = bits & 0xFFFFFFFF; 00651 int aValues = values & 0xFFFFFFFF; 00652 int bBits = bits >> 32; 00653 int bValues = values >> 32; 00654 00655 AT91C_BASE_PIOA->PIO_SODR = (int)( aBits & aValues ); 00656 AT91C_BASE_PIOA->PIO_CODR = (int)( aBits & ~aValues ); 00657 AT91C_BASE_PIOB->PIO_SODR = (int)( bBits & bValues ); 00658 AT91C_BASE_PIOB->PIO_CODR = (int)( bBits & ~bValues ); 00659 } 00660 00661 /** 00662 Set a batch of IO lines to a particular direction (in or out) at once. 00663 @param bits The bitmask containing the IO lines you'd like to configure - see \ref IoBits. Must be 00664 a longlong to accommodate all 64 bits. 00665 @param output true to set the lines as outputs, false to set them as inputs 00666 */ 00667 void Io_SetDirectionBits( longlong bits, bool output ) 00668 { 00669 if(output) 00670 { 00671 AT91C_BASE_PIOA->PIO_OER = bits & 0xFFFFFFFF; 00672 AT91C_BASE_PIOB->PIO_OER = bits >> 32; 00673 } 00674 else 00675 { 00676 AT91C_BASE_PIOA->PIO_ODR = bits & 0xFFFFFFFF; 00677 AT91C_BASE_PIOB->PIO_ODR = bits >> 32; 00678 } 00679 } 00680 00681 /** 00682 Set a batch of IO lines to being general IOs at once. 00683 @param bits The bitmask containing the IO lines you'd like to configure - see \ref IoBits. Must be 00684 a longlong to accommodate all 64 bits. 00685 @param enable true to configure the lines as PIOs, false un-configure them 00686 */ 00687 void Io_SetPioBits( longlong bits, bool enable ) 00688 { 00689 if(enable) 00690 { 00691 AT91C_BASE_PIOA->PIO_PER = bits & 0xFFFFFFFF; 00692 AT91C_BASE_PIOB->PIO_PER = bits >> 32; 00693 } 00694 else 00695 { 00696 AT91C_BASE_PIOA->PIO_PER = bits & 0xFFFFFFFF; 00697 AT91C_BASE_PIOB->PIO_PER = bits >> 32; 00698 } 00699 } 00700 00701 int Io_SetPortA( int value ) 00702 { 00703 AT91C_BASE_PIOA->PIO_SODR = (int)( Io.portAMask & value ); 00704 AT91C_BASE_PIOA->PIO_CODR = (int)( Io.portAMask & ~value ); 00705 return CONTROLLER_OK; 00706 } 00707 00708 int Io_GetPortA( ) 00709 { 00710 return Io.portAMask & AT91C_BASE_PIOA->PIO_PDSR; 00711 } 00712 00713 int Io_SetPortB( int value ) 00714 { 00715 AT91C_BASE_PIOB->PIO_SODR = (int)( Io.portBMask & value ); 00716 AT91C_BASE_PIOB->PIO_CODR = (int)( Io.portBMask & ~value ); 00717 return CONTROLLER_OK; 00718 } 00719 00720 int Io_GetPortB( ) 00721 { 00722 return Io.portBMask & AT91C_BASE_PIOB->PIO_PDSR; 00723 } 00724 00725 int Io_SetPortAMask( int value ) 00726 { 00727 Io.portAMask = value; 00728 return CONTROLLER_OK; 00729 } 00730 00731 int Io_GetPortAMask( ) 00732 { 00733 return Io.portAMask; 00734 } 00735 00736 int Io_SetPortBMask( int value ) 00737 { 00738 Io.portBMask = value; 00739 return CONTROLLER_OK; 00740 } 00741 00742 int Io_GetPortBMask( ) 00743 { 00744 return Io.portBMask; 00745 } 00746 00747 // static 00748 void Io_Init() 00749 { 00750 Io.init++; 00751 00752 /* Enable the peripheral clock. */ 00753 AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOA; 00754 AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOB; 00755 00756 Io.portAMask = 0; 00757 Io.portBMask = 0; 00758 } 00759 00760 // static 00761 void Io_Deinit() 00762 { 00763 Io.init--; 00764 } 00765 00766 /** 00767 Get a bitmask with the output values of all the IO lines. 00768 @return A longlong (64 bit) value with the values of the output lines. 00769 00770 \b Example 00771 \code 00772 longlong values = Io_GetValueBits( ); 00773 if( values & IO_PA18_BIT ) 00774 { 00775 // then we know PA18 is configured as an output 00776 } 00777 \endcode 00778 */ 00779 longlong Io_GetValueBits( ) 00780 { 00781 return ( ((longlong)AT91C_BASE_PIOB->PIO_PDSR) << 32 ) | AT91C_BASE_PIOA->PIO_PDSR; 00782 } 00783 00784 /** 00785 Get a bitmask with the state of the internal pullup for all the IO lines. 00786 @return A longlong (64 bit) value with the status of the pullups. 00787 00788 \b Example 00789 \code 00790 longlong pullups = Io_GetPullupBits( ); 00791 if( pullups & IO_PA18_BIT ) 00792 { 00793 // then we know PA18 has its pullup turned on 00794 } 00795 \endcode 00796 */ 00797 longlong Io_GetPullupBits( ) 00798 { 00799 return ( ((longlong)AT91C_BASE_PIOB->PIO_PPUSR) << 32 ) | AT91C_BASE_PIOA->PIO_PPUSR; 00800 } 00801 00802 /** 00803 Get a bitmask indicating PIO configuration for all the IO lines. 00804 @return A longlong (64 bit) value specifying which lines are configured as PIOs. 00805 00806 \b Example 00807 \code 00808 longlong pios = Io_GetPioBits( ); 00809 if( pios & IO_PA18_BIT ) 00810 { 00811 // then we know PA18 is configured as a PIO 00812 } 00813 \endcode 00814 */ 00815 longlong Io_GetPioBits( ) 00816 { 00817 return ( ((longlong)AT91C_BASE_PIOB->PIO_PSR) << 32 ) | AT91C_BASE_PIOA->PIO_PSR; 00818 } 00819 00820 /** 00821 Get a bitmask indicating the in-or-out configuration for all the IO lines. 00822 @return A longlong (64 bit) value specifying which lines are inputs and which are outputs. Non-zero 00823 values indicate that a line is configured as an output. 00824 00825 \b Example 00826 \code 00827 longlong directions = Io_GetDirectionBits( ); 00828 if( directions & IO_PA18_BIT ) 00829 { 00830 // then we know PA18 is configured as an output 00831 } 00832 \endcode 00833 */ 00834 longlong Io_GetDirectionBits( ) 00835 { 00836 return ( ((longlong)AT91C_BASE_PIOB->PIO_OSR) << 32 ) | AT91C_BASE_PIOA->PIO_OSR; 00837 } 00838 00839 /** @} 00840 */ 00841 00842 #ifdef OSC 00843 00844 /** \defgroup IoOSC IO - OSC 00845 Control any pin's direction and output from OSC. 00846 00847 The IO system allows for the manual manipulation of individual signal lines on the Make Controller. 00848 Proceed with care if you're using these at the same time as any of the other subsystems, as most 00849 other subsystems rely on the IO system internally to maintain control of the appropriate signal lines. 00850 \ingroup OSC 00851 00852 \section devices Devices 00853 There are 64 IO's on the Make Controller, numbered 0 - 63. 00854 - IOs <b>0 - 31</b> correspond to \b PortA 00855 - IOs <b>32 - 63 </b> correspond to \b PortB. 00856 00857 \section properties Properties 00858 Each IO has four properties: 00859 - output 00860 - value 00861 - pullup 00862 - active 00863 00864 \par Output 00865 The \b output property sets whether the IO is an output. 00866 A value of \b 1 makes it an output, and a value of \b 0 makes it an input. 00867 For example, to make pin 4 an output, send a message like 00868 \verbatim /io/4/output 1\endverbatim 00869 Send the message 00870 \verbatim /io/4/output 0\endverbatim 00871 to make it an input. 00872 00873 \par Pullup 00874 The \b pullup property determines whether a given IOs pullup resistor is enabled. 00875 To enable it on IO 2, send the message 00876 \verbatim /io/2/pullup 1\endverbatim 00877 and to disable it, send the message 00878 \verbatim /io/2/pullup 0\endverbatim 00879 00880 \par Value 00881 Writing the \b value property sets the on/off value of a given IO. 00882 The IO system only permits digital IO so, we only want to send ones and zeros as values. 00883 For example, to activate pin 4, send a message like 00884 \verbatim /io/4/value 1\endverbatim 00885 Change the argument 1 to a 0 to turn it off. 00886 Reading the \b value property returns the value of a given IO. 00887 For example, to read pin 4, send a message like 00888 \verbatim /io/4/value\endverbatim 00889 00890 \par Active 00891 The \b active property corresponds to the active state of an IO. 00892 Read whether IO 0 is active by sending the message 00893 \verbatim /io/0/active \endverbatim 00894 You can set the active flag by sending 00895 \verbatim /io/0/active 1 \endverbatim 00896 */ 00897 00898 #include "osc.h" 00899 #include "string.h" 00900 #include "stdio.h" 00901 00902 // Need a list of property names 00903 // MUST end in zero 00904 static char* IoOsc_Name = "io"; 00905 static char* IoOsc_IndexIntPropertyNames[] = { "active", "value", "output", "pio", "pullup", 0 }; // must have a trailing 0 00906 00907 int IoOsc_IndexIntPropertySet( int index, int property, int value ); 00908 int IoOsc_IndexIntPropertyGet( int index, int property ); 00909 00910 static char* IoOsc_IntPropertyNames[] = { "porta", "portamask", "portb", "portbmask", 0 }; // must have a trailing 0 00911 int IoOsc_IntPropertySet( int property, int value ); 00912 int IoOsc_IntPropertyGet( int property ); 00913 00914 // Returns the name of the subsystem 00915 const char* IoOsc_GetName( ) 00916 { 00917 return IoOsc_Name; 00918 } 00919 00920 // Now getting a message. This is actually a part message, with the first 00921 // part (the subsystem) already parsed off. 00922 int IoOsc_ReceiveMessage( int channel, char* message, int length ) 00923 { 00924 int status = Osc_IndexIntReceiverHelper( channel, message, length, 00925 IO_PIN_COUNT, IoOsc_Name, 00926 IoOsc_IndexIntPropertySet, IoOsc_IndexIntPropertyGet, 00927 IoOsc_IndexIntPropertyNames ); 00928 00929 if ( status != CONTROLLER_OK ) 00930 { 00931 status = Osc_IntReceiverHelper( channel, message, length, 00932 IoOsc_Name, 00933 IoOsc_IntPropertySet, IoOsc_IntPropertyGet, 00934 IoOsc_IntPropertyNames ); 00935 } 00936 00937 if ( status != CONTROLLER_OK ) 00938 return Osc_SendError( channel, IoOsc_Name, status ); 00939 return CONTROLLER_OK; 00940 } 00941 00942 // Set the index, property with the value 00943 int IoOsc_IndexIntPropertySet( int index, int property, int value ) 00944 { 00945 switch ( property ) 00946 { 00947 case 0: 00948 if(value) 00949 Io_Start( index, false ); 00950 else 00951 Io_Stop( index ); 00952 break; 00953 case 1: 00954 Io_SetValue( index, value ); 00955 break; 00956 case 2: 00957 Io_SetDirection( index, value ); 00958 break; 00959 case 3: 00960 Io_SetPio( index, value ); 00961 break; 00962 case 4: 00963 Io_SetPullup( index, value ); 00964 break; } 00965 return CONTROLLER_OK; 00966 } 00967 00968 // Get the indexed property 00969 int IoOsc_IndexIntPropertyGet( int index, int property ) 00970 { 00971 int value = 0; 00972 switch ( property ) 00973 { 00974 case 0: 00975 value = Io_GetActive( index ); 00976 break; 00977 case 1: 00978 value = Io_GetValue( index ); 00979 break; 00980 case 2: 00981 value = Io_GetDirection( index ); 00982 break; 00983 case 3: 00984 value = Io_GetPio( index ); 00985 break; 00986 case 4: 00987 value = Io_GetPullup( index ); 00988 break; 00989 } 00990 00991 return value; 00992 } 00993 00994 00995 // Set the property with the value 00996 int IoOsc_IntPropertySet( int property, int value ) 00997 { 00998 switch ( property ) 00999 { 01000 case 0: 01001 Io_SetPortA( value ); 01002 break; 01003 case 1: 01004 Io_SetPortAMask( value ); 01005 break; 01006 case 2: 01007 Io_SetPortB( value ); 01008 break; 01009 case 3: 01010 Io_SetPortBMask( value ); 01011 break; 01012 } 01013 return CONTROLLER_OK; 01014 } 01015 01016 // Get the indexed property 01017 int IoOsc_IntPropertyGet( int property ) 01018 { 01019 int value = 0; 01020 switch ( property ) 01021 { 01022 case 0: 01023 value = Io_GetPortA( ); 01024 break; 01025 case 1: 01026 value = Io_GetPortAMask( ); 01027 break; 01028 case 2: 01029 value = Io_GetPortB( ); 01030 break; 01031 case 3: 01032 value = Io_GetPortBMask( ); 01033 break; 01034 } 01035 return value; 01036 } 01037 01038 #endif 01039 01040 01041 01042 01043
The Make Controller Kit is an open source project maintained by MakingThings.
    MakingThings code is released under the Apache 2.0 license.
    Bug tracker, development wiki and status can be found at http://dev.makingthings.com.
    This document was last updated on 18 May 2009.
  
