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.