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