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

dipswitch.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 // MakingThings - Make Controller Board - 2006
00019 
00020 /** \file dipswitch.c 
00021   DIP Switch.
00022   Functions for reading from the 8-position DIP switch on the Make Application Board.
00023 */
00024 
00025 #include "io.h"
00026 #include "dipswitch.h"
00027 #include "spi.h"
00028 #include "config.h"
00029 #include "stdio.h"
00030 
00031 #define DIPSWITCH_DEVICE 2
00032 
00033 static int DipSwitch_Start( void );
00034 static int DipSwitch_Stop( void );
00035 
00036 typedef struct
00037 {
00038   int users;
00039   int lastValue;
00040   #ifdef OSC
00041   int autosend;
00042   #endif
00043 } DipSwitchSubsystem;
00044 
00045 DipSwitchSubsystem* DipSwitch;
00046 
00047 /** \defgroup DipSwitch DIP Switch
00048 * The DIP Switch subsystem reads values in from the 8 position DIP Switch (0 - 255) on the Application Board.
00049   Mask off the appropriate bits in the value returned from the DIP switch to determine whether a particular channel is on or off.
00050   
00051   See the <a href="http://www.makingthings.com/documentation/tutorial/application-board-overview/user-interface">
00052   Application Board overview</a> for details.
00053 * \ingroup Libraries
00054 * @{
00055 */
00056 
00057 /**
00058   Sets whether the DIP Switch is active.
00059   @param state An integer specifying the state of the DIP Switch - 1 (on) or 0 (off).
00060   @return Zero on success.
00061   
00062   \b Example
00063   \code
00064   // enable the DIP switch
00065   DipSwitch_SetActive(1);
00066   \endcode
00067 */
00068 int DipSwitch_SetActive( int state )
00069 {
00070   if ( state )
00071   {
00072     if( DipSwitch == NULL )
00073     {
00074       DipSwitch = MallocWait( sizeof( DipSwitchSubsystem ), 100 );
00075       DipSwitch->users = 0;
00076       DipSwitch->lastValue = 0;
00077       #ifdef OSC
00078       DipSwitch->autosend = DipSwitch_GetAutoSend( true );
00079       #endif
00080       return DipSwitch_Start(  );
00081     }
00082   }
00083   else
00084   {
00085     if( DipSwitch )
00086       Free( DipSwitch );
00087     return DipSwitch_Stop(  );
00088   }
00089   return CONTROLLER_OK;
00090 }
00091 
00092 /**
00093   Returns the active state of the DIP Switch.
00094   @return The active state of the DIP Switch - 1 (active) or 0 (inactive).
00095   
00096   \b Example
00097   \code
00098   if( DipSwitch_GetActive() )
00099   {
00100     // DIP switch is active
00101   }
00102   else
00103   {
00104     // DIP switch is not active
00105   }
00106   \endcode
00107 */
00108 int DipSwitch_GetActive( )
00109 {
00110   return DipSwitch->users > 0;
00111 }
00112 
00113 /** 
00114   Read the current configuration of the on-board DIP switch.
00115   @return An integer from 0-255 indicating the current configuration of the DIP switch.
00116   
00117   \b Example
00118   \code
00119   int dip_switch = DipSwitch_GetValue();
00120   // now dip_switch has a bitmask of all 8 channels of the DIP switch
00121   \endcode
00122 */
00123 int DipSwitch_GetValue( )
00124 {
00125   DipSwitch_SetActive( 1 );
00126   if ( DipSwitch->users == 0 )
00127   {
00128     int status = DipSwitch_Start();
00129     if ( status != CONTROLLER_OK )
00130       return status;
00131   }
00132 
00133   Spi_Lock();
00134 
00135   unsigned char c[ 2 ];
00136 
00137   c[ 0 ] = 0xFE;
00138   c[ 1 ] = 0xFF;
00139   
00140   Spi_ReadWriteBlock( DIPSWITCH_DEVICE, c, 2 );
00141 
00142   Spi_Unlock();
00143 
00144   int r = ( c[ 1 ] & 0x01 ) << 8 | 
00145           ( c[ 0 ] & 0x01 ) << 7 | 
00146             c[ 1 ] >> 1; 
00147 
00148   return r;
00149 }
00150 
00151 /**
00152   Read a single channel's value.
00153   This is a convenience function that relies on DipSwitch_GetValue()
00154   internally, but extracts the value for a given channel.
00155   @param channel The channel (0-7) you'd like to read.
00156   return true if the channel is on, false if it's off.
00157   @see DipSwitch_GetValue( )
00158   
00159   \b Example
00160   \code
00161   if(DipSwitch_GetValueChannel(4) )
00162   {
00163     // DIP switch channel 4 is on
00164   }
00165   else
00166   {
00167     // DIP switch channel 4 is off
00168   }
00169   // now dip_switch has a bitmask of all 8 channels of the DIP switch
00170   \endcode
00171 */
00172 bool DipSwitch_GetValueChannel( int channel )
00173 {
00174   if( channel < 0 || channel > 7 )
00175     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00176 
00177   int val = DipSwitch_GetValue();
00178   if( val < 0 )
00179     return false;
00180   else
00181     return ((val >> channel) & 0x1);
00182 }
00183 
00184 /** @}
00185 */
00186 
00187 int DipSwitch_Start()
00188 {
00189   int status;
00190   if ( DipSwitch->users++ == 0 )
00191   {
00192     // Start the SPI
00193     status = Spi_Start( DIPSWITCH_DEVICE );
00194     if ( status != CONTROLLER_OK )
00195     {
00196       DipSwitch->users--;
00197       return status;
00198     }
00199     
00200     // Configure the channel
00201     status = Spi_Configure( DIPSWITCH_DEVICE, 8, 4, 0, 1 );
00202     if ( status != CONTROLLER_OK )
00203     {
00204       // Undo all the setup.  Sigh.
00205       DipSwitch_Stop();
00206       return status;
00207     }
00208   }
00209   return CONTROLLER_OK;
00210 }
00211 
00212 int DipSwitch_Stop()
00213 {
00214   if ( DipSwitch->users <= 0 )
00215     return CONTROLLER_ERROR_TOO_MANY_STOPS;
00216   
00217   if ( --DipSwitch->users == 0 )
00218     Spi_Stop( DIPSWITCH_DEVICE );
00219 
00220   return CONTROLLER_OK;
00221 }
00222 
00223 #ifdef OSC
00224 
00225 /** \defgroup DIPSwitchOSC DIP Switch - OSC
00226   Read the Application Board's DIP Switch via OSC.
00227   \ingroup OSC
00228   
00229   \section devices Devices
00230   There's a single DIP Switch the Make Application Board. Because there's
00231   only one device, a device index is not included in any OSC messages to the
00232   DIP Switch.
00233   
00234   \section properties Properties
00235   The DIP Switch has the following properties
00236   - value
00237   - autosend
00238   - active
00239 
00240   \par Value
00241   The \b value property corresponds to current configuration of the DIP Switch.
00242   The DIP switch is 8-position, which means that it will send a value from 0-255
00243   depending on the orientation of each of the switches. Mask off the appropriate bits to 
00244   determine the value of a particular channel.
00245   \par
00246   Because you can only ever \em read the value of an input, you'll never
00247   want to include an argument at the end of your OSC message to read the value.\n
00248   To read from the DIP Switch, send the message
00249   \verbatim /dipswitch/value \endverbatim
00250 
00251   \par Autosend
00252   The \b autosend property corresponds to whether the DIP Switch will automatically send a message
00253   when its value changes.
00254   To tell the DIP Swtich to automatically send messages, send the message
00255   \verbatim /dipswitch/autosend 1 \endverbatim
00256   To have the DIP Switch stop sending messages automatically, send the message
00257   \verbatim /dipswitch/autosend 0 \endverbatim
00258   All autosend messages send at the same interval.  You can set this interval, in 
00259   milliseconds, by sending the message
00260   \verbatim /system/autosend-interval 10 \endverbatim
00261   so that messages will be sent every 10 milliseconds.  This can be anywhere from 1 to 5000 milliseconds.
00262   You also need to select whether the board should send to you over USB or Ethernet.  Send
00263   \verbatim /system/autosend-usb 1 \endverbatim
00264   to send via USB, and 
00265   \verbatim /system/autosend-udp 1 \endverbatim
00266   to send via Ethernet.  Via Ethernet, the board will send messages to the last address it received a message from.
00267   
00268   \par Active
00269   The \b active property corresponds to the active state of the DIP Switch.
00270   If the DIP Switch is set to be active, no other tasks will be able to
00271   use its I/O lines.  If you're not seeing appropriate
00272   responses to your messages to the DIP Switch, check whether it's 
00273   locked by sending the message
00274   \verbatim /dipswitch/active \endverbatim
00275   \par
00276   You can set the active flag by sending
00277   \verbatim /dipswitch/active 1 \endverbatim
00278 */
00279 
00280 #include "osc.h"
00281 
00282 bool DipSwitch_GetAutoSend( bool init )
00283 {
00284   DipSwitch_SetActive( 1 );
00285   if( init )
00286   {
00287     int autosend;
00288     Eeprom_Read( EEPROM_DIPSWITCH_AUTOSEND, (uchar*)&autosend, 4 );
00289     DipSwitch->autosend = (autosend == 1 ) ? 1 : 0;
00290   }
00291   return DipSwitch->autosend;
00292 }
00293 
00294 void DipSwitch_SetAutoSend( int onoff )
00295 {
00296   DipSwitch_SetActive( 1 );
00297   if( DipSwitch->autosend != onoff )
00298   {
00299     DipSwitch->autosend = onoff;
00300     Eeprom_Write( EEPROM_DIPSWITCH_AUTOSEND, (uchar*)&onoff, 4 );
00301   }
00302 }
00303 
00304 static char* DipSwitchOsc_Name = "dipswitch";
00305 static char* DipSwitchOsc_PropertyNames[] = { "active", "value", "autosend",  0 }; // must have a trailing 0
00306 
00307 int DipSwitchOsc_PropertySet( int property, int value );
00308 int DipSwitchOsc_PropertyGet( int property );
00309 
00310 const char* DipSwitchOsc_GetName( void )
00311 {
00312   return DipSwitchOsc_Name;
00313 }
00314 
00315 int DipSwitchOsc_ReceiveMessage( int channel, char* message, int length )
00316 {
00317   int status = Osc_IntReceiverHelper( channel, message, length, 
00318                                       DipSwitchOsc_Name,
00319                                       DipSwitchOsc_PropertySet, DipSwitchOsc_PropertyGet, 
00320                                       DipSwitchOsc_PropertyNames );
00321 
00322   if ( status != CONTROLLER_OK )
00323     return Osc_SendError( channel, DipSwitchOsc_Name, status );
00324   return CONTROLLER_OK;
00325 }
00326 
00327 // Set the index LED, property with the value
00328 int DipSwitchOsc_PropertySet( int property, int value )
00329 {
00330   switch ( property )
00331   {
00332     case 0: 
00333       DipSwitch_SetActive( value );
00334       break;      
00335     case 2: 
00336       DipSwitch_SetAutoSend( value );
00337       break;  
00338   }
00339   return CONTROLLER_OK;
00340 }
00341 
00342 // Get the property
00343 int DipSwitchOsc_PropertyGet( int property )
00344 {
00345   int value = 0;
00346   switch ( property )
00347   {
00348     case 0:
00349       value = DipSwitch_GetActive( );
00350       break;
00351     case 1:
00352       value = DipSwitch_GetValue( );
00353       break;
00354     case 2:
00355       value = DipSwitch_GetAutoSend( false );
00356       break;
00357   }
00358   
00359   return value;
00360 }
00361 
00362 int DipSwitchOsc_Async( int channel )
00363 {
00364   int newMsgs = 0;
00365   if( !DipSwitch_GetAutoSend( false ) )
00366     return newMsgs;
00367   char address[ OSC_SCRATCH_SIZE ];
00368   int value = DipSwitch_GetValue( );
00369   
00370   if( value != DipSwitch->lastValue )
00371   {
00372     DipSwitch->lastValue = value;
00373     snprintf( address, OSC_SCRATCH_SIZE, "/%s/value", DipSwitchOsc_Name );
00374     Osc_CreateMessage( channel, address, ",i", value );
00375     newMsgs++;
00376   }
00377 
00378   return newMsgs;
00379 }
00380 
00381 #endif

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.