- 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.