MakingThings
  • Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

io.c

Go to the documentation of this file.
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.