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

system.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 /** \file system.c  
00019   System Control.
00020   Functions for monitoring and controlling the system.
00021 */
00022 
00023 #include "stdio.h"
00024 #include "string.h"
00025 #include "ctype.h"
00026 #include "io.h"
00027 #include "eeprom.h"
00028 #include "system.h"
00029 #include "config.h"
00030 #include "AT91SAM7X256.h"
00031 #include "portmacro.h"
00032 #include "FreeRTOSConfig.h"
00033 #include "network.h"
00034 
00035 /* the Atmel header file doesn't define these. */
00036 #ifdef AT91SAM7X256_H
00037 # define AT91C_RSTC_KEY_PASSWORD  (0xa5 << 24)
00038 
00039 # define AT91C_IROM     ((char *)(0x3 << 20))
00040 # define AT91C_IROM_SIZE    (8 << 10)
00041 #endif
00042 
00043 int PortFreeMemory( void );
00044 void StackAuditTask( void* p );
00045 void kill( void );
00046 void vPortDisableAllInterrupts( void );
00047 #define ASYNC_INIT -10
00048 #define ASYNC_INACTIVE -1
00049 
00050 typedef struct System_
00051 {
00052   char name[ SYSTEM_MAX_NAME + 1 ]; // allotted EEPROM space is 100, but leave room for \0!
00053   int users;
00054   void* StackAuditPtr;
00055   #ifdef OSC
00056   char scratch1[ OSC_SCRATCH_SIZE ];
00057   int asyncDestination;
00058   int autoInterval;
00059   #endif // OSC
00060 } SystemS;
00061 
00062 SystemS* System;
00063 
00064 /** \defgroup System System
00065     The System subsystem monitors and controls several aspects of the system. 
00066 
00067 * \ingroup Core
00068 * @{
00069 */
00070 
00071 /**
00072   Sets whether the System subsystem is active.
00073   @param state An integer specifying the state system
00074   @return Zero on success.
00075   
00076   \b Example
00077   \code
00078   // enable the System subsystem
00079   System_SetActive(1);
00080   \endcode
00081 */
00082 int System_SetActive( int state )
00083 {
00084   if( state )
00085   {
00086     if( System == NULL )
00087     {
00088       System = MallocWait( sizeof( SystemS ), 100 );
00089       System->name[0] = 0;
00090       System->StackAuditPtr = NULL;
00091       #ifdef OSC
00092       System->asyncDestination = ASYNC_INIT;
00093       System->asyncDestination = System_GetAsyncDestination( );
00094       System->autoInterval = ASYNC_INIT;
00095       System->autoInterval = System_GetAutoSendInterval( );
00096       #endif
00097     }
00098     return CONTROLLER_OK;
00099   }
00100   else
00101   {
00102     if ( System != NULL )
00103     {
00104       Free( System );
00105       System = NULL;
00106     }
00107     return CONTROLLER_OK;
00108   }
00109 }
00110 
00111 /**
00112   Returns the active state of the subsystem.
00113   @return The active state of the subsystem - 1 (active) or 0 (inactive).
00114   
00115   \b Example
00116   \code
00117   if(System_GetActive())
00118   {
00119     // System is active
00120   }
00121   else
00122   {
00123     // System is inactive
00124   }
00125   \endcode
00126 */
00127 int System_GetActive( )
00128 {
00129   return System != NULL;
00130 }
00131 
00132 /**
00133   Returns the free size of the heap.
00134   The heap size is set in config.h in the constant CONTROLLER_HEAPSIZE.
00135   Any calls to Malloc will take their memory from the heap.  This allows
00136   you to check how much heap is remaining.
00137   @return The size free memory.
00138   
00139   \b Example
00140   \code
00141   // see how much memory is available
00142   int freemem = System_GetFreeMemory();
00143   \endcode
00144 */
00145 int System_GetFreeMemory( void )
00146 {
00147   return PortFreeMemory();
00148 }
00149 
00150 /**
00151   Gets the board's Serial Number.
00152   Each board has a serial number, although it's not necessarily unique
00153   as you can reset it as you please.
00154   
00155   The serial number is used to determine the Ethernet MAC address, so boards
00156   on the same network need to have unique serial numbers.
00157   @return CONTROLLER_OK ( = 0 ).
00158   
00159   \b Example
00160   \code
00161   // get this board's serial number
00162   int sernum = System_GetSerialNumber();
00163   \endcode
00164 */
00165 int System_GetSerialNumber( void )
00166 {
00167   int serial;
00168   if ( Eeprom_Read( EEPROM_SYSTEM_SERIAL_NUMBER, (uchar*)&serial, 4 ) == CONTROLLER_OK )
00169     return serial & 0xFFFF;
00170   return 0;
00171 }
00172 
00173 /**
00174   Sets the Serial Number. 
00175   Note that this can be changed by the user at 
00176   any time, but that it is used in the \ref Network subsystem to form the last 
00177   two bytes of the network MAC address, so ideally units on the same network
00178   should have unique serial numbers.
00179   @return 0 on success.
00180   
00181   \b Example
00182   \code
00183   // set the serial number to 12345
00184   System_SetSerialNumber(12345);
00185   \endcode
00186 */
00187 int System_SetSerialNumber( int serial )
00188 {
00189   serial &= 0xFFFF;
00190   return Eeprom_Write( EEPROM_SYSTEM_SERIAL_NUMBER, (uchar*)&serial, 4 );
00191 }
00192 
00193 /**
00194   Returns the board to SAM-BA mode.
00195   When a board is in SAM-BA mode, it is ready to have new firmware uploaded to it. 
00196   Upon successful completion, the board will be reset and begin running SAM-BA.  
00197   This function does not clear the GPNVM2 bit, so if you unplug/replug you'll be running
00198   your old code again.
00199   @param sure Confirm you're sure you want to do this.
00200   @return nonzero on failure.  Successful completion does not return.
00201   
00202   \b Example
00203   \code
00204   // prepare to be uploaded
00205   System_SetSamba(1);
00206   \endcode
00207 */
00208 int System_SetSamba( int sure )
00209 {
00210   if ( sure )
00211   {
00212     vPortDisableAllInterrupts();
00213 
00214     /* Disable the USB pullup. */
00215 #if ( CONTROLLER_VERSION == 90 )
00216   AT91C_BASE_PIOB->PIO_PER = AT91C_PIO_PB11;
00217   AT91C_BASE_PIOB->PIO_OER = AT91C_PIO_PB11;
00218   AT91C_BASE_PIOB->PIO_SODR = AT91C_PIO_PB11;
00219 #elif ( CONTROLLER_VERSION == 95 || CONTROLLER_VERSION == 100 )
00220   AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA11;
00221   AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA11;
00222   AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA11;
00223 #elif ( CONTROLLER_VERSION == 200 )
00224   AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA30;
00225   AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA30;
00226   AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA30;
00227 #endif
00228 
00229     /* Steal the PIT for the pullup disable delay. */
00230     AT91C_BASE_PITC->PITC_PIMR = (
00231       (configCPU_CLOCK_HZ + (16 * 1000 / 2))
00232       / (16 * 1000)
00233     ) | AT91C_PITC_PITEN
00234     ;
00235 
00236     /* Dummy read to clear picnt. */
00237     __asm__ __volatile__ ("ldr r3, %0" :: "m" (AT91C_BASE_PITC->PITC_PIVR) : "r3");
00238 
00239     /* Loop until picnt passes 200ms */
00240     while((AT91C_BASE_PITC->PITC_PIIR & AT91C_PITC_PICNT) < (200 << 20));
00241 
00242     /* Reset onboard and offboard peripherals, but not processor */
00243     while(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_SRCMP);
00244     AT91C_BASE_RSTC->RSTC_RMR = AT91C_RSTC_KEY_PASSWORD;
00245     AT91C_BASE_RSTC->RSTC_RCR = AT91C_RSTC_KEY_PASSWORD
00246   | AT91C_RSTC_PERRST
00247       | AT91C_RSTC_EXTRST
00248     ;
00249     while(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_SRCMP);
00250 
00251     /*
00252        The ROM code copies itself to RAM, where it runs.
00253        That works fine when running SAM-BA in the usual way (booting with GPNVM2 clear).
00254        However, it is actually copying from the remap page; not the native ROM address.
00255        So with GPNVM2 set, that means the FLASH image (and only 8KB or so of that) gets copied, 
00256        which is not a recipe for success.
00257        This workaround would be unnecessary if the ROM just copied itself from 0x300000 instead of 0x0.
00258        If not for the fact that the ROM code doesn't appear to issue a remap command (the exception vectors 
00259        ordinarily remain in ROM instead of being remapped), this workaround would not be possible.  Either 
00260        it doesn't remap or it does it an even number of times.  To address the problem, we copy the ROM 
00261        image to the RAM, ourselves and issue a remap so that when we run the image, RAM will already be remapped, 
00262        and the image copy that it performs will be from the RAM to itself, therefore harmless. This does have 
00263        the side effect that when SAM-BA runs other code (via the G command), the remap page will be 
00264        remapped to RAM.  Any code run that way which assumes otherwise will break.  We are not using SAM-BA 
00265        in that way.
00266      */
00267 
00268     /* From here on, we have to be in asm to prevent the compiler from trying to use RAM in any way. */
00269     __asm__ __volatile__ (
00270     /* Copy the ROM image to RAM. */
00271     " mov r6, %0    \n" /* save ROM address for later */
00272     " b 2f    \n"
00273     "1:       \n"
00274     " ldmia %0!, {r7} \n"
00275     " str r7, [%2]  \n"
00276     " add %2, %2, #4  \n"
00277     "2:       \n"
00278     " cmp %0, %1    \n"
00279     " bmi 1b    \n"
00280 
00281     /* Remap so that image copy in SAM-BA is RAM to RAM. */
00282     /* We know that the remap page is not currently remapped because we just did an AT91C_RSTC_PERRST. */
00283     " mov r7, %4    \n"
00284     " str r7, %3    \n"
00285 
00286     /* Start running the ROM. */
00287     " bx  r6    \n"
00288     :
00289     :
00290     "r"(AT91C_IROM),
00291     "r"(AT91C_IROM + AT91C_IROM_SIZE),
00292     "r"(AT91C_ISRAM),
00293     "m"(AT91C_BASE_MC->MC_RCR),
00294     "n"(AT91C_MC_RCB)
00295     :
00296     "r7", "r6"
00297     );
00298   }
00299 
00300   // Never will do this
00301   return 1;
00302 }
00303 
00304 /**
00305   Gives the board a name.
00306   The name must be alpha-numeric - only letters and numbers.  It can help you
00307   determine one board from another when there are more than one connected to 
00308   your system.
00309   @param name A string specifying the board's name
00310   @return 0 on success.
00311   
00312   \b Example
00313   \code
00314   // give the board a special name
00315   System_SetName("my very special controller");
00316   \endcode
00317 */
00318 int System_SetName( char* name )
00319 {
00320   System_SetActive( 1 );
00321   int length = strlen( name );
00322   if( length > SYSTEM_MAX_NAME )
00323     return CONTROLLER_ERROR_STRING_TOO_LONG;
00324   
00325   strcpy( System->name, name ); // update the name in our buffer
00326   int i;
00327   char* ptr = name;
00328   for( i = 0; i <= length; i++ ) // have to do this because Eeprom_Write can only go 32 at a time.
00329   {
00330     Eeprom_Write( EEPROM_SYSTEM_NAME + i, (uchar*)ptr++, 1 );
00331   }
00332 
00333   return CONTROLLER_OK;
00334 }
00335 
00336 /**
00337   Read the board's name.
00338   @return The board's name as a string.
00339   
00340   \b Example
00341   \code
00342   char* board_name = System_GetName();
00343   \endcode
00344 */
00345 char* System_GetName( )
00346 {
00347   System_SetActive( 1 );
00348   if( System->name[0] == 0 )
00349   {
00350     char* ptr;
00351     ptr = System->name;
00352     int i;
00353     bool legal = false;
00354     for( i = 0; i <= SYSTEM_MAX_NAME; i++ )
00355     {
00356       Eeprom_Read( EEPROM_SYSTEM_NAME + i, (uchar*)ptr, 1 );
00357       if( *ptr == 0 )
00358         break;
00359       if( !isalnum( *ptr ) && *ptr != ' ' )
00360       {
00361         legal = false;
00362         break;
00363       }
00364       legal = true;
00365       
00366       if( i == SYSTEM_MAX_NAME && *ptr != 0 )
00367         *ptr = 0;
00368       ptr++;
00369     }
00370 
00371     if( !legal )
00372     {
00373       strcpy( System->name, "Make Controller Kit" );
00374       System_SetName( System->name );
00375     }
00376   }
00377 
00378   return System->name;
00379 }
00380 
00381 /**
00382   Reset the board.
00383   Will reboot the board if the parameter sure is true.
00384   @param sure confirms the request is true.
00385   @return 0 on success.
00386   
00387   \b Example
00388   \code
00389   // reboot
00390   System_SetReset(1);
00391   \endcode
00392 */
00393 int System_SetReset( int sure )
00394 {
00395   if ( sure )
00396     kill( );
00397 
00398   return 1;
00399 }
00400 
00401 /** @}
00402 */
00403 
00404 void kill( void )
00405 {
00406   AT91C_BASE_RSTC->RSTC_RCR = ( AT91C_RSTC_EXTRST | AT91C_RSTC_PROCRST | AT91C_RSTC_PERRST | (0xA5 << 24 ) );
00407 }
00408 
00409 #ifdef OSC
00410 #include "osc.h"
00411 
00412 void System_StackAudit( int on_off )
00413 {
00414   System_SetActive( 1 );
00415   if( System->StackAuditPtr == NULL && on_off )
00416     System->StackAuditPtr = TaskCreate( StackAuditTask, "StackAudit", 700, 0, 5 );
00417   
00418   if( System->StackAuditPtr != NULL && !on_off )
00419   {
00420     TaskDelete( System->StackAuditPtr );
00421     System->StackAuditPtr = NULL;
00422   }
00423 }
00424 
00425 void StackAuditTask( void* p )
00426 {
00427   (void)p;
00428   void* task = NULL;
00429   while( 1 )
00430   {
00431     task = TaskGetNext( task );
00432     int stackremaining = TaskGetRemainingStack( task );
00433     if( stackremaining < 50 )
00434     {
00435       Led_SetState( 1 );
00436       Debug( DEBUG_WARNING, "Warning: Stack running low on task %s. %d bytes left.", TaskGetName( task ), stackremaining );
00437     }
00438 
00439     int freemem = System_GetFreeMemory( );
00440     if( freemem < 100 )
00441     {
00442       Led_SetState( 1 );
00443       Debug( DEBUG_WARNING, "Warning: System memory running low. %d bytes left.", freemem );
00444     }
00445     
00446     Sleep( 5 );
00447   }
00448 }
00449 
00450 void System_SetAsyncDestination( int dest )
00451 {
00452   System_SetActive( 1 );
00453   if( dest < ASYNC_INACTIVE || dest > (OSC_CHANNEL_COUNT-1) )
00454     return;
00455   else
00456   {
00457     if( System->asyncDestination != dest )
00458     {
00459       System->asyncDestination = dest;
00460       Eeprom_Write( EEPROM_OSC_ASYNC_DEST, (uchar*)&dest, 4 );
00461     }
00462   }
00463 }
00464 
00465 int System_GetAsyncDestination( )
00466 {
00467   System_SetActive( 1 );
00468   if( System->asyncDestination == ASYNC_INIT )
00469   {
00470     int async;
00471     Eeprom_Read( EEPROM_OSC_ASYNC_DEST, (uchar*)&async, 4 );
00472     if( async >= 0 && async <= (OSC_CHANNEL_COUNT-1) )
00473       System->asyncDestination = async;
00474     else
00475       System->asyncDestination = ASYNC_INACTIVE;
00476   }
00477   return System->asyncDestination;
00478 }
00479 
00480 void System_SetAutoSendInterval( int interval )
00481 {
00482   System_SetActive( 1 );
00483   if( interval < 0 || interval > 5000 )
00484     return;
00485   else
00486   {
00487     if( System->autoInterval != interval )
00488     {
00489       System->autoInterval = interval;
00490       Eeprom_Write( EEPROM_OSC_ASYNC_INTERVAL, (uchar*)&interval, 4 );
00491     }
00492   }
00493 }
00494 
00495 int System_GetAutoSendInterval( )
00496 {
00497   System_SetActive( 1 );
00498   if( System->autoInterval == ASYNC_INIT )
00499   {
00500     int interval;
00501     Eeprom_Read( EEPROM_OSC_ASYNC_INTERVAL, (uchar*)&interval, 4 );
00502     if( interval >= 0 && interval <= 5000 )
00503       System->autoInterval = interval;
00504     else
00505       System->autoInterval = 10;
00506   }
00507   return System->autoInterval;
00508 }
00509 
00510 /** \defgroup SystemOSC System - OSC
00511   System controls many of the logistics of the Controller Board via OSC.
00512   \ingroup OSC
00513    
00514     \section devices Devices
00515     There's only one System, so a device index is not used in OSC messages to it.
00516    
00517     \section properties Properties
00518     System has eight properties:
00519     - name
00520     - freememory
00521     - samba
00522     - reset
00523     - serialnumber
00524     - version
00525     - stack-audit
00526     - task-report
00527     - active
00528 
00529     \par Name
00530     The \b name property allows you to give a board its own name.  The name can only contain 
00531     alphabetic characters and numbers.
00532     To set your board's name, send the message
00533     \verbatim /system/name "My Board"\endverbatim
00534     To read the board's name, send the message
00535     \verbatim /system/name \endverbatim
00536     The board will respond by sending back an OSC message with the board's name.
00537     
00538     \par Free Memory
00539     The \b freememory property corresponds to the amount of free memory on the Controller Board.
00540     This value is read-only.  To get the amount of free memory, send the message
00541     \verbatim /system/freememory \endverbatim
00542     The board will respond by sending back an OSC message with the amount of free memory.
00543    
00544     \par Samba
00545     The \b samba property is a write-only value that returns the board to a state in which it's ready
00546     to receive new firmware via SAM-BA or mchelper.  Once you've set the board to SAM-BA state,
00547     unplug and replug the power on the board before uploading new firmware.
00548     \par
00549     To set the board in SAM-BA state, send the message
00550     \verbatim /system/samba 1 \endverbatim
00551     and don't forget to power cycle the board.  Remember the board won't be able to send/receive OSC
00552     messages until a new program is uploaded to it.
00553    
00554     \par Reset
00555     The \b reset property is a write-only value that reboots the board.
00556     To reset the board, send the message
00557     \verbatim /system/reset 1 \endverbatim
00558    
00559     \par Serial Number
00560     The \b serialnumber property corresponds to the unique serial number on each Controller Board.
00561     This value can be used in situations where a unique value needs to be used to identify a board.
00562     The serial number can be both read and written.
00563     \par
00564     To read the board's serial number, send the message
00565     \verbatim /system/serialnumber \endverbatim
00566    
00567     \par Version
00568     The \b version property corresponds to the of the firmware currently running on the board.
00569     This is read-only.
00570     \par
00571     To read the board's version, send the message
00572     \verbatim /system/version \endverbatim
00573 
00574     \par Stack Audit
00575     The \b stack-audit property can fire up a task that will monitor the stack usage
00576     of all tasks running on the board.  If the remaining stack of any of the tasks drops below 50 bytes,
00577     the board will attempt to send an OSC message back via the \ref Debug system to let you know.
00578     \par
00579     This uses up quite a lot of processor time, so it's really only designed to be used in a 
00580     debug context.
00581     \par
00582     To start up the stack audit, send the message
00583     \verbatim /system/stack-audit 1 \endverbatim
00584     \par
00585     and turn it off by sending 
00586     \verbatim /system/stack-audit 0 \endverbatim
00587     
00588     \par Task Report
00589     The \b task-report property is a read-only property that will generate a list of all the tasks running 
00590     on your Make Controller, first giving the name of the task followed by the task's remaining stack.
00591     \par
00592     To see the tasks running on your board, send the message
00593     \verbatim /system/task-report \endverbatim
00594    
00595     \par Active
00596     The \b active property corresponds to the active state of System.
00597     If System is set to be inactive, it will not respond to any other OSC messages. 
00598     If you're not seeing appropriate
00599     responses to your messages to System, check the whether it's
00600     active by sending a message like
00601     \verbatim /system/active \endverbatim
00602     \par
00603     You can set the active flag by sending
00604     \verbatim /system/active 1 \endverbatim
00605 */
00606 
00607 static char* SystemOsc_Name = "system";
00608 static char* SystemOsc_PropertyNames[] = { "active", "freememory", "samba", "reset", 
00609                                             "serialnumber", "version",
00610                                             "name", "info-internal", "info", "stack-audit", 
00611                                             "task-report", "autosend-usb", "autosend-udp", "autosend-interval", 0 }; // must have a trailing 0
00612 
00613 int SystemOsc_PropertySet( int property, char* typedata, int channel );
00614 int SystemOsc_PropertyGet( int property, int channel );
00615 
00616 const char* SystemOsc_GetName( void )
00617 {
00618   return SystemOsc_Name;
00619 }
00620 // need to allow this to accept non-int arguments
00621 int SystemOsc_ReceiveMessage( int channel, char* message, int length )
00622 {
00623   int status = Osc_GeneralReceiverHelper( channel, message, length, 
00624                                 SystemOsc_Name,
00625                                 SystemOsc_PropertySet, SystemOsc_PropertyGet, 
00626                                 SystemOsc_PropertyNames );
00627 
00628   if ( status != CONTROLLER_OK )
00629     return Osc_SendError( channel, SystemOsc_Name, status );
00630 
00631   return CONTROLLER_OK;
00632 }
00633 
00634 int SystemOsc_Poll( )
00635 {
00636   return CONTROLLER_OK;
00637 }
00638 
00639 // Set the index LED, property with the value
00640 int SystemOsc_PropertySet( int property, char* typedata, int channel )
00641 {
00642   int value = 0;
00643   switch ( property )
00644   {
00645     case 0: // active
00646     {
00647       int count = Osc_ExtractData( typedata, "i", &value );
00648       if ( count != 1 )
00649         return Osc_SubsystemError( channel, SystemOsc_Name, "Incorrect data - need an int" );
00650 
00651       System_SetActive( value );
00652       break;
00653     }
00654     case 2: // samba
00655     {
00656       int count = Osc_ExtractData( typedata, "i", &value );
00657       if ( count != 1 )
00658         return Osc_SubsystemError( channel, SystemOsc_Name, "Incorrect data - need an int" );
00659 
00660       System_SetSamba( value );
00661       break;
00662     }
00663     case 3: // reset
00664     {
00665       int count = Osc_ExtractData( typedata, "i", &value );
00666       if ( count != 1 )
00667         return Osc_SubsystemError( channel, SystemOsc_Name, "Incorrect data - need an int" );
00668 
00669       System_SetReset( value );
00670       break;
00671     }
00672     case 4: // serialnumber
00673     {
00674       int count = Osc_ExtractData( typedata, "i", &value );
00675       if ( count != 1 )
00676         return Osc_SubsystemError( channel, SystemOsc_Name, "Incorrect data - need an int" );
00677 
00678       System_SetSerialNumber( value );
00679       break;
00680     }
00681     case 6: // name
00682     {
00683       char* address;
00684       int count = Osc_ExtractData( typedata, "s", &address );
00685       if ( count != 1 ) 
00686         return Osc_SubsystemError( channel, SystemOsc_Name, "Incorrect data - need a string" );
00687 
00688       System_SetName( address );
00689       break;
00690     }
00691     case 9: // stack-audit
00692     {
00693       int count = Osc_ExtractData( typedata, "i", &value );
00694       if ( count != 1 )
00695         return Osc_SubsystemError( channel, SystemOsc_Name, "Incorrect data - need an int" );
00696 
00697       System_StackAudit( value );
00698       break;
00699     }
00700     case 11: // autosend-usb
00701     {
00702       int count = Osc_ExtractData( typedata, "i", &value );
00703       if ( count != 1 )
00704         return Osc_SubsystemError( channel, SystemOsc_Name, "Incorrect data - need an int" );
00705       if( value )
00706         System_SetAsyncDestination( OSC_CHANNEL_USB );
00707       else
00708       {
00709         if( System_GetAsyncDestination( ) == OSC_CHANNEL_USB )
00710           System_SetAsyncDestination( ASYNC_INACTIVE );
00711       }
00712       break;
00713     }
00714     case 12: // autosend-udp
00715     {
00716       int count = Osc_ExtractData( typedata, "i", &value );
00717       if ( count != 1 )
00718         return Osc_SubsystemError( channel, SystemOsc_Name, "Incorrect data - need an int" );
00719       if( value )
00720         System_SetAsyncDestination( OSC_CHANNEL_UDP );
00721       else
00722       {
00723         if( System_GetAsyncDestination( ) == OSC_CHANNEL_UDP )
00724           System_SetAsyncDestination( ASYNC_INACTIVE );
00725       }
00726       break;
00727     }
00728     case 13: // autosend-interval
00729     {
00730       int count = Osc_ExtractData( typedata, "i", &value );
00731       if ( count != 1 )
00732         return Osc_SubsystemError( channel, SystemOsc_Name, "Incorrect data - need an int" );
00733 
00734       System_SetAutoSendInterval( value );
00735       break;
00736     }
00737   }
00738   return CONTROLLER_OK;
00739 }
00740 
00741 // Get the property
00742 int SystemOsc_PropertyGet( int property, int channel )
00743 {
00744   int value = 0;
00745   //char address[ OSC_SCRATCH_SIZE ];
00746   switch ( property )
00747   {
00748     case 0: // active
00749       value = System_GetActive( );
00750       snprintf( System->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", SystemOsc_Name, SystemOsc_PropertyNames[ property ] ); 
00751       Osc_CreateMessage( channel, System->scratch1, ",i", value ); 
00752       break;
00753     case 1: // freememory
00754       value = System_GetFreeMemory( );
00755       snprintf( System->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", SystemOsc_Name, SystemOsc_PropertyNames[ property ] ); 
00756       Osc_CreateMessage( channel, System->scratch1, ",i", value ); 
00757       break;
00758     case 4: // serialnumber
00759       value = System_GetSerialNumber( );
00760       snprintf( System->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", SystemOsc_Name, SystemOsc_PropertyNames[ property ] ); 
00761       Osc_CreateMessage( channel, System->scratch1, ",i", value ); 
00762       break;  
00763     case 5: // version
00764     {
00765       char versionString[50];
00766       snprintf( versionString, 50, "%s %d.%d.%d", FIRMWARE_NAME, FIRMWARE_MAJOR_VERSION, FIRMWARE_MINOR_VERSION, FIRMWARE_BUILD_NUMBER );
00767       snprintf( System->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", SystemOsc_Name, SystemOsc_PropertyNames[ property ] ); 
00768       Osc_CreateMessage( channel, System->scratch1, ",s", versionString ); 
00769       break;
00770     }
00771     case 6: // name
00772     {
00773       char* name;
00774       name = System_GetName( );
00775       snprintf( System->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", SystemOsc_Name, SystemOsc_PropertyNames[ property ] ); 
00776       Osc_CreateMessage( channel, System->scratch1, ",s", name ); 
00777       break;
00778     }
00779     case 7: // info-internal
00780     case 8: // info
00781     {
00782       int a0, a1, a2, a3;
00783       { // put these in their own context so the local variables aren't lying around on the stack for the whole message
00784         char ipAddr[25];
00785         char* sysName = System_GetName( );
00786         int serialnum = System_GetSerialNumber( );
00787         char sysVersion[25];
00788         snprintf( sysVersion, 25, "%s %d.%d.%d", FIRMWARE_NAME, FIRMWARE_MAJOR_VERSION, FIRMWARE_MINOR_VERSION, FIRMWARE_BUILD_NUMBER );
00789         int freemem = System_GetFreeMemory( );
00790         #ifdef MAKE_CTRL_NETWORK
00791         if( Network_GetAddress( &a0, &a1, &a2, &a3 ) != CONTROLLER_OK )
00792           a0 = a1 = a2 = a3 = -1;
00793         #else
00794         a0 = a1 = a2 = a3 = -1;
00795         #endif // MAKE_CTRL_NETWORK
00796         snprintf( ipAddr, 25, "%d.%d.%d.%d", a0, a1, a2, a3 );
00797         snprintf( System->scratch1, OSC_SCRATCH_SIZE, "/%s/%s-a", SystemOsc_Name, SystemOsc_PropertyNames[ property ] ); 
00798         Osc_CreateMessage( channel, System->scratch1, ",sissi", sysName, serialnum, ipAddr, sysVersion, freemem );
00799       }
00800       {
00801       char gateway[25];
00802       char mask[25];
00803       int dhcp;
00804       int webserver;
00805       int oscUdpListen;
00806       int oscUdpSend; 
00807       #ifdef MAKE_CTRL_NETWORK
00808       if( Network_GetGateway( &a0, &a1, &a2, &a3 ) != CONTROLLER_OK )
00809         a0 = a1 = a2 = a3 = -1;
00810       snprintf( gateway, 25, "%d.%d.%d.%d", a0, a1, a2, a3 );
00811       if( Network_GetMask( &a0, &a1, &a2, &a3 ) != CONTROLLER_OK )
00812         a0 = a1 = a2 = a3 = -1;
00813       snprintf( mask, 25, "%d.%d.%d.%d", a0, a1, a2, a3 );
00814       dhcp = Network_GetDhcpEnabled( );
00815       webserver = 0; // webserver no longer in core. TODO - update system-info to not use webserver
00816       oscUdpListen = NetworkOsc_GetUdpListenPort( );
00817       oscUdpSend = NetworkOsc_GetUdpSendPort( );
00818       #else
00819       a0 = a1 = a2 = a3 = -1;
00820       snprintf( gateway, 25, "%d.%d.%d.%d", a0, a1, a2, a3 );
00821       snprintf( mask, 25, "%d.%d.%d.%d", a0, a1, a2, a3 );
00822       dhcp = 0;
00823       webserver = 0;
00824       oscUdpListen = 0;
00825       oscUdpSend = 0;
00826       #endif // MAKE_CTRL_NETWORK
00827       
00828       snprintf( System->scratch1, OSC_SCRATCH_SIZE, "/%s/%s-b", SystemOsc_Name, SystemOsc_PropertyNames[ property ] ); 
00829       Osc_CreateMessage( channel, System->scratch1, ",iissii", dhcp, webserver, gateway, mask, oscUdpListen, oscUdpSend );
00830       }
00831       break;
00832     }
00833     case 9: // stack-audit
00834       if( System->StackAuditPtr == NULL )
00835         value = 0;
00836       else
00837         value = 1;
00838       snprintf( System->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", SystemOsc_Name, SystemOsc_PropertyNames[ property ] ); 
00839       Osc_CreateMessage( channel, System->scratch1, ",i", value ); 
00840       break;
00841     case 10: // task-report
00842     {
00843       int numOfTasks = GetNumberOfTasks( ) - 1;  // don't count the IDLE task
00844       int i;
00845       void* task = NULL;
00846       char* taskName = "";
00847       snprintf( System->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", SystemOsc_Name, SystemOsc_PropertyNames[ property ] ); 
00848       
00849       for( i = 0; i < numOfTasks; i++ )
00850       {
00851         task = TaskGetNext( task );
00852         value = TaskGetRemainingStack( task );
00853         taskName = TaskGetName( task );
00854         Osc_CreateMessage( channel, System->scratch1, ",si", taskName, value ); 
00855       }
00856       break;
00857     }
00858     case 11: // autosend-usb
00859       value = ( System_GetAsyncDestination( ) == OSC_CHANNEL_USB ) ? 1 : 0;
00860       snprintf( System->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", SystemOsc_Name, SystemOsc_PropertyNames[ property ] ); 
00861       Osc_CreateMessage( channel, System->scratch1, ",i", value ); 
00862       break;
00863     case 12: // autosend-udp
00864       value = ( System_GetAsyncDestination( ) == OSC_CHANNEL_UDP ) ? 1 : 0;
00865       snprintf( System->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", SystemOsc_Name, SystemOsc_PropertyNames[ property ] ); 
00866       Osc_CreateMessage( channel, System->scratch1, ",i", value ); 
00867       break;
00868     case 13: // autosend-interval
00869       value = System_GetAutoSendInterval( );
00870       snprintf( System->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", SystemOsc_Name, SystemOsc_PropertyNames[ property ] ); 
00871       Osc_CreateMessage( channel, System->scratch1, ",i", value ); 
00872       break; 
00873   }
00874   
00875   return CONTROLLER_OK;
00876 }
00877 
00878 #endif // OSC

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.