- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

# stepper.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 stepper.c
    00021   Stepper Motor Controls.
    00022   Methods for controlling up to 2 stepper motors with the Make Application Board.
    00023 */
    00024
    00025 #include "stepper.h"
    00026 #include "io.h"
    00027 #include "fasttimer.h"
    00028 #include "config.h"
    00029
    00030 #include "AT91SAM7X256.h"
    00031
    00032 #if ( APPBOARD_VERSION == 50 )
    00033   #define STEPPER_0_IO_0 IO_PA02
    00034   #define STEPPER_0_IO_1 IO_PA02
    00035   #define STEPPER_0_IO_2 IO_PA02
    00036   #define STEPPER_0_IO_3 IO_PA02
    00037   #define STEPPER_1_IO_0 IO_PA02
    00038   #define STEPPER_1_IO_1 IO_PA02
    00039   #define STEPPER_1_IO_2 IO_PA02
    00040   #define STEPPER_1_IO_3 IO_PA02
    00041 #endif
    00042 #if ( APPBOARD_VERSION == 90 || APPBOARD_VERSION == 95 || APPBOARD_VERSION == 100 )
    00043   #define STEPPER_0_IO_0 IO_PA24
    00044   #define STEPPER_0_IO_1 IO_PA05
    00045   #define STEPPER_0_IO_2 IO_PA06
    00046   #define STEPPER_0_IO_3 IO_PA02
    00047   #define STEPPER_1_IO_0 IO_PB25
    00048   #define STEPPER_1_IO_1 IO_PA25
    00049   #define STEPPER_1_IO_2 IO_PA26
    00050   #define STEPPER_1_IO_3 IO_PB23
    00051 #endif
    00052
    00053 #define STEPPER_COUNT 2
    00054
    00055 typedef struct StepperControlS
    00056 {
    00057   int users;
    00058   unsigned int bipolar : 1;
    00059   unsigned int halfStep : 1;
    00060   int speed;
    00061   int duty;
    00062   int acceleration;
    00063   int positionRequested;
    00064   int position;
    00065   int io[ 4 ];
    00066   unsigned timerRunning : 1;
    00067   FastTimerEntry fastTimerEntry;
    00068 } StepperControl;
    00069
    00070 typedef struct StepperS
    00071 {
    00072   int users;
    00073   StepperControl* control[ STEPPER_COUNT ];
    00074 } Stepper_;
    00075
    00076 void Stepper_IRQCallback( int id );
    00077
    00078 static int Stepper_Start( int index );
    00079 static int Stepper_Stop( int index );
    00080 static int Stepper_Init( void );
    00081 static int Stepper_GetIo( int index, int io );
    00082 static void Stepper_SetDetails( StepperControl* s );
    00083 static void Stepper_SetUnipolarHalfStepOutput( StepperControl *s, int position );
    00084 static void Stepper_SetUnipolarOutput( StepperControl *s, int position );
    00085 static void Stepper_SetBipolarOutput( StepperControl *s, int position );
    00086 static void Stepper_SetBipolarHalfStepOutput( StepperControl *s, int position );
    00087
    00088 void Stepper_SetOn( int index, int* portAOn, int* portBOn );
    00089 void Stepper_SetOff( int index, int* portAOff, int* portBOff );
    00090 void Stepper_SetAll( int portAOn, int portBOn, int portAOff, int portBOff );
    00091
    00092 Stepper_* Stepper;
    00093
    00094 /** \defgroup Stepper Stepper
    00095   The Stepper Motor subsystem provides speed and position control for one or two stepper motors.
    00096   Up to 2 stepper motors can be controlled with the Make Application Board.
    00097   Specify settings for your stepper motor by setting whether it's:
    00098   - bipolar or unipolar
    00099   - normal of half-stepping
    00100
    00101   \section Positioning
    00102   You can generally use the stepper motor in 2 modes - \b absolute positioning or \b relative positioning.
    00103
    00104   For absolute positioning, call Stepper_SetPositionRequested() with the desired position, and the motor will move there.
    00105   You can read back the stepper's position at any point along the way to determine where it is at a given moment.  The board
    00106   keeps an internal count of how many steps the motor has taken in order to keep track of where it is.
    00107
    00108   For relative positioning, use Stepper_Step( ) to simply move a number of steps from the current position.
    00109
    00110   See the <a href="http://www.makingthings.com/documentation/how-to/stepper-motor">Stepper Motor how-to</a>
    00111   for more detailed info on hooking up a stepper motor to the Make Controller.
    00112 * \ingroup Libraries
    00113 * @{
    00114 */
    00115
    00116 /**
    00117   Sets whether the specified Stepper is active.
    00118   @param index An integer specifying which stepper (0 or 1).
    00119   @param state An integer specifying the active state - 1 (active) or 0 (inactive).
    00120   @return Zero on success.
    00121
    00122   \b Example
    00123   \code
    00124   // enable stepper 1
    00125   Stepper_SetActive(1, 1);
    00126   \endcode
    00127 */
    00128 int Stepper_SetActive( int index, int state )
    00129 {
    00130   if ( index < 0 || index >= STEPPER_COUNT )
    00131     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00132
    00133   if ( state )
    00134   {
    00135     if( Stepper == NULL ) // if our subsystem has not been fired up
    00136     {
    00137       int retVal = Stepper_Init( );
    00138       if( retVal != CONTROLLER_OK )
    00139         return retVal;
    00140     }
    00141
    00142     if( Stepper->control[ index ] == NULL ) // if this particular stepper has not been fired up
    00143     {
    00144       Stepper->control[ index ] = MallocWait( sizeof( StepperControl ), 100 );
    00145       Stepper->control[ index ]->users = 0;
    00146       if( Stepper_Start( index ) != CONTROLLER_OK )
    00147         return CONTROLLER_ERROR_SYSTEM_NOT_ACTIVE;
    00148     }
    00149
    00150     if( Stepper->control[ index ] != NULL )
    00151       return CONTROLLER_OK;
    00152     else
    00153       return CONTROLLER_ERROR_SYSTEM_NOT_ACTIVE;
    00154   }
    00155   else
    00156     return Stepper_Stop( index );
    00157 }
    00158
    00159 /**
    00160   Check whether the stepper is active or not
    00161   @param index An integer specifying which stepper (0-1).
    00162   @return State - 1 (active) or 0 (inactive).
    00163
    00164   \b Example
    00165   \code
    00166   if( Stepper_GetActive(1) )
    00167   {
    00168     // Stepper 1 is active
    00169   }
    00170   else
    00171   {
    00172     // Stepper 1 is inactive
    00173   }
    00174   \endcode
    00175 */
    00176 int Stepper_GetActive( int index )
    00177 {
    00178   if ( index < 0 || index >= STEPPER_COUNT )
    00179     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00180
    00181   if( Stepper == NULL )
    00182     return 0;
    00183   else
    00184     return Stepper->control[ index ] != NULL;
    00185 }
    00186
    00187 /**
    00188   Set the position of the specified stepper motor.
    00189   Note that this will not ask the stepper to move.  It will simply update
    00190   the position that the stepper thinks its at.  To move the stepper, see
    00191   Stepper_SetPositionRequested() or Stepper_Step().
    00192   @param index An integer specifying which stepper (0 or 1).
    00193   @param position An integer specifying the stepper position.
    00194   @return status (0 = OK).
    00195
    00196   \b Example
    00197   \code
    00198   // reset stepper 1 to call its current position 0
    00199   Stepper_SetPosition(1, 0);
    00200   \endcode
    00201 */
    00202 int Stepper_SetPosition( int index, int position )
    00203 {
    00204   if ( index < 0 || index >= STEPPER_COUNT )
    00205     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00206
    00207   if ( Stepper_SetActive( index, 1 ) != CONTROLLER_OK )
    00208     return CONTROLLER_ERROR_SYSTEM_NOT_ACTIVE;
    00209
    00210   StepperControl* s = Stepper->control[ index ];
    00211
    00212   DisableFIQFromThumb();
    00213   s->position = position;
    00214   s->positionRequested = position;
    00215   EnableFIQFromThumb();
    00216
    00217   Stepper_SetDetails( s );
    00218
    00219   return CONTROLLER_OK;
    00220 }
    00221
    00222 /**
    00223   Set the destination position for a stepper motor.
    00224   This will start the stepper moving the given number of
    00225   steps at the current speed, as set by Stepper_SetSpeed().
    00226
    00227   While it's moving, you can call Stepper_GetPosition() to read
    00228   its current position.
    00229   @param index An integer specifying which stepper (0 or 1).
    00230   @param positionRequested An integer specifying the desired stepper position.
    00231   @return status (0 = OK).
    00232
    00233   \b Example
    00234   \code
    00235   // start moving stepper 0 1500 steps
    00236   Stepper_SetPositionRequested(0, 1500);
    00237   \endcode
    00238 */
    00239 int Stepper_SetPositionRequested( int index, int positionRequested )
    00240 {
    00241   if ( index < 0 || index >= STEPPER_COUNT )
    00242     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00243
    00244   if ( Stepper_SetActive( index, 1 ) != CONTROLLER_OK )
    00245     return CONTROLLER_ERROR_SYSTEM_NOT_ACTIVE;
    00246
    00247   StepperControl* s = Stepper->control[ index ];
    00248   DisableFIQFromThumb();
    00249   s->positionRequested = positionRequested;
    00250   EnableFIQFromThumb();
    00251
    00252   Stepper_SetDetails( s );
    00253
    00254   return CONTROLLER_OK;
    00255 }
    00256
    00257 /**
    00258   Set the speed at which a stepper will move.
    00259   This is a number of ms per step, rather than the more common steps per second.
    00260   Arranging it this way makes it easier to express as an integer.
    00261   Fastest speed is 1ms / step (1000 steps per second) and slowest is many seconds.
    00262   @param index An integer specifying which stepper (0 or 1).
    00263   @param speed An integer specifying the stepper speed in ms per step
    00264   @return status (0 = OK).
    00265
    00266   \b Example
    00267   \code
    00268   // set the speed to 1ms / step (1000 steps per second)
    00269   Stepper_SetSpeed(0, 1);
    00270   \endcode
    00271 */
    00272 int Stepper_SetSpeed( int index, int speed )
    00273 {
    00274   if ( index < 0 || index >= STEPPER_COUNT )
    00275     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00276
    00277   if ( Stepper_SetActive( index, 1 ) != CONTROLLER_OK )
    00278     return CONTROLLER_ERROR_SYSTEM_NOT_ACTIVE;
    00279
    00280   StepperControl* s = Stepper->control[ index ];
    00281
    00282   s->speed = speed * 1000;
    00283
    00284   DisableFIQFromThumb();
    00285   FastTimer_SetTime( &s->fastTimerEntry, s->speed );
    00286   EnableFIQFromThumb();
    00287
    00288   Stepper_SetDetails( s );
    00289
    00290   return CONTROLLER_OK;
    00291 }
    00292
    00293 /**
    00294   Get the speed at which a stepper will move.
    00295   Read the value previously set for the speed parameter.
    00296   @param index An integer specifying which stepper (0 or 1).
    00297   @return The speed (0 - 1023), or 0 on error.
    00298
    00299   \b Example
    00300   \code
    00301   int step0_speed = Stepper_GetSpeed(0);
    00302   // now step0_speed has the speed of stepper 0
    00303   \endcode
    00304 */
    00305 int Stepper_GetSpeed( int index )
    00306 {
    00307   if ( index < 0 || index >= STEPPER_COUNT )
    00308     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00309
    00310   if ( Stepper_SetActive( index, 1 ) != CONTROLLER_OK )
    00311     return CONTROLLER_ERROR_SYSTEM_NOT_ACTIVE;
    00312
    00313   return Stepper->control[ index ]->speed;
    00314 }
    00315
    00316 /**
    00317   Read the current position of a stepper motor.
    00318   @param index An integer specifying which stepper (0 or 1).
    00319   @return The position, 0 on error.
    00320
    00321   \b Example
    00322   \code
    00323   int step0_pos = Stepper_GetPosition(0);
    00324   // now step0_pos has the current position of stepper 0
    00325   \endcode
    00326 */
    00327 int Stepper_GetPosition( int index )
    00328 {
    00329   if ( index < 0 || index >= STEPPER_COUNT )
    00330     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00331
    00332   if ( Stepper_SetActive( index, 1 ) != CONTROLLER_OK )
    00333     return CONTROLLER_ERROR_SYSTEM_NOT_ACTIVE;
    00334
    00335   return Stepper->control[ index ]->position;
    00336 }
    00337
    00338 /**
    00339   Read the destination position of a stepper motor.
    00340   This indicates where the stepper is ultimately headed.  To see
    00341   where it actually is, see Stepper_GetPosition().
    00342   @param index An integer specifying which stepper (0 or 1).
    00343   @return The position and 0 on error
    00344
    00345   \b Example
    00346   \code
    00347   int step1_destination = Stepper_GetPositionRequested(1);
    00348   // step1_destination has the requested position for stepper 1
    00349   \endcode
    00350 */
    00351 int Stepper_GetPositionRequested( int index )
    00352 {
    00353   if ( index < 0 || index >= STEPPER_COUNT )
    00354     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00355
    00356   if ( Stepper_SetActive( index, 1 ) != CONTROLLER_OK )
    00357     return CONTROLLER_ERROR_SYSTEM_NOT_ACTIVE;
    00358
    00359   return Stepper->control[ index ]->positionRequested;
    00360 }
    00361
    00362 /**
    00363   Simply take a number of steps from wherever the motor is currently positioned.
    00364   This function will move the motor a given number of steps from the current position.
    00365   @param index An integer specifying which stepper (0 or 1).
    00366   @param steps An integer specifying the number of steps.  Can be negative to go in reverse.
    00367   @return status (0 = OK).
    00368
    00369   \b Example
    00370   \code
    00371   // take 1200 steps forward from our current position
    00372   Stepper_Step(0, 1200);
    00373   \endcode
    00374 */
    00375 int Stepper_Step( int index, int steps )
    00376 {
    00377   if ( index < 0 || index >= STEPPER_COUNT )
    00378     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00379
    00380   if ( Stepper_SetActive( index, 1 ) != CONTROLLER_OK )
    00381     return CONTROLLER_ERROR_SYSTEM_NOT_ACTIVE;
    00382
    00383   StepperControl* s = Stepper->control[ index ];
    00384   DisableFIQFromThumb();
    00385   s->positionRequested = (s->position + steps);
    00386   EnableFIQFromThumb();
    00387
    00388   Stepper_SetDetails( s );
    00389   return CONTROLLER_OK;
    00390 }
    00391
    00392 /**
    00393   Set the duty - from 0 to 1023.  The default is for 100% power (1023).
    00394   @param index An integer specifying which stepper (0 or 1).
    00395   @param duty An integer specifying the stepper duty (0 - 1023).
    00396   @return status (0 = OK).
    00397
    00398   \b Example
    00399   \code
    00400   // set stepper 0 to half power
    00401   Stepper_SetDuty(0, 512);
    00402   \endcode
    00403 */
    00404 int Stepper_SetDuty( int index, int duty )
    00405 {
    00406   if ( index < 0 || index >= STEPPER_COUNT )
    00407     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00408
    00409   if ( Stepper_SetActive( index, 1 ) != CONTROLLER_OK )
    00410     return CONTROLLER_ERROR_SYSTEM_NOT_ACTIVE;
    00411
    00412   StepperControl* s = Stepper->control[ index ];
    00413   s->duty = duty;
    00414
    00415   // Fire the PWM's up
    00416   int pwm = index * 2;
    00417   Pwm_Set( pwm, duty );
    00418   Pwm_Set( pwm + 1, duty );
    00419
    00420   return CONTROLLER_OK;
    00421 }
    00422
    00423 /**
    00424   Get the duty
    00425   Read the value previously set for the duty.
    00426   @param index An integer specifying which stepper (0 or 1).
    00427   @return The duty (0 - 1023), or 0 on error.
    00428
    00429   \b Example
    00430   \code
    00431   int step1_duty = Stepper_GetDuty(1);
    00432   // step1_duty has the current duty for stepper 1
    00433   \endcode
    00434 */
    00435 int Stepper_GetDuty( int index )
    00436 {
    00437   if ( index < 0 || index >= STEPPER_COUNT )
    00438     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00439
    00440   if ( Stepper_SetActive( index, 1 ) != CONTROLLER_OK )
    00441     return CONTROLLER_ERROR_SYSTEM_NOT_ACTIVE;
    00442
    00443   return Stepper->control[ index ]->duty;
    00444 }
    00445
    00446 /**
    00447   Declare whether the stepper is bipolar or not.
    00448   Default is bipolar.
    00449   @param index An integer specifying which stepper (0 or 1).
    00450   @param bipolar An integer 1 for bipolar, 0 for unipolar
    00451   @return status (0 = OK).
    00452
    00453   \b Example
    00454   \code
    00455   // set stepper 1 to unipolar
    00456   Stepper_SetBipolar(1, 0);
    00457   \endcode
    00458 */
    00459 int Stepper_SetBipolar( int index, int bipolar )
    00460 {
    00461   if ( index < 0 || index >= STEPPER_COUNT )
    00462     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00463
    00464   if ( Stepper_SetActive( index, 1 ) != CONTROLLER_OK )
    00465     return CONTROLLER_ERROR_SYSTEM_NOT_ACTIVE;
    00466
    00467   StepperControl* s = Stepper->control[ index ];
    00468   s->bipolar = bipolar;
    00469
    00470   return CONTROLLER_OK;
    00471 }
    00472
    00473 /**
    00474   Get the bipolar setting
    00475   Read the value previously set for bipolar.
    00476   @param index An integer specifying which stepper (0 or 1).
    00477   @return 1 for bipolar or 0 for unipolar.
    00478
    00479   \b Example
    00480   \code
    00481   if( Stepper_GetBipolar(1) )
    00482   {
    00483     // stepper 1 is bipolar
    00484   }
    00485   else
    00486   {
    00487     // stepper 1 is unipolar
    00488   }
    00489   \endcode
    00490 */
    00491 int Stepper_GetBipolar( int index )
    00492 {
    00493   if ( index < 0 || index >= STEPPER_COUNT )
    00494     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00495
    00496   if ( Stepper_SetActive( index, 1 ) != CONTROLLER_OK )
    00497     return CONTROLLER_ERROR_SYSTEM_NOT_ACTIVE;
    00498
    00499   return Stepper->control[ index ]->bipolar;
    00500 }
    00501
    00502 /**
    00503   Declare whether the stepper is in half stepping mode or not.
    00504   Default is not - i.e. in full step mode.
    00505   @param index An integer specifying which stepper (0 or 1).
    00506   @param halfStep An integer specifying 1 for half step, 0 for full step
    00507   @return status (0 = OK).
    00508
    00509   \b Example
    00510   \code
    00511   // set stepper 1 to half step mode
    00512   Stepper_SetHalfStep(1, 1);
    00513   \endcode
    00514 */
    00515 int Stepper_SetHalfStep( int index, int halfStep )
    00516 {
    00517   if ( index < 0 || index >= STEPPER_COUNT )
    00518     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00519
    00520   if ( Stepper_SetActive( index, 1 ) != CONTROLLER_OK )
    00521     return CONTROLLER_ERROR_SYSTEM_NOT_ACTIVE;
    00522
    00523   StepperControl* s = Stepper->control[ index ];
    00524   s->halfStep = halfStep;
    00525
    00526   return CONTROLLER_OK;
    00527 }
    00528
    00529 /**
    00530   Read whether the stepper is in half stepping mode or not.
    00531   @param index An integer specifying which stepper (0 or 1).
    00532   @return the HalfStep setting.
    00533
    00534   \b Example
    00535   \code
    00536   if( Stepper_GetHalfStep(1) )
    00537   {
    00538     // stepper 1 is in half step mode
    00539   }
    00540   else
    00541   {
    00542     // stepper 1 is in full step mode
    00543   }
    00544   \endcode
    00545 */
    00546 int Stepper_GetHalfStep( int index )
    00547 {
    00548   if ( index < 0 || index >= STEPPER_COUNT )
    00549     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00550
    00551   if ( Stepper_SetActive( index, 1 ) != CONTROLLER_OK )
    00552     return CONTROLLER_ERROR_SYSTEM_NOT_ACTIVE;
    00553
    00554   return Stepper->control[ index ]->halfStep;
    00555 }
    00556
    00557
    00558 /** @}
    00559 */
    00560
    00561 int Stepper_Start( int index )
    00562 {
    00563   static int status; // why does this not seem to work at -O2 when this is not declared as static?
    00564
    00565   if ( index < 0 || index >= STEPPER_COUNT )
    00566     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00567
    00568   StepperControl* sc = Stepper->control[ index ];
    00569   if ( sc->users++ == 0 )
    00570   {
    00571     status = Pwm_Start( index * 2 );
    00572     if ( status != CONTROLLER_OK )
    00573     {
    00574       sc->users--;
    00575       Stepper->users--;
    00576       return status;
    00577     }
    00578
    00579     status = Pwm_Start( index * 2 + 1 );
    00580     if ( status != CONTROLLER_OK )
    00581     {
    00582       Pwm_Stop( index * 2 );
    00583       sc->users--;
    00584       Stepper->users--;
    00585       return status;
    00586     }
    00587
    00588     // Fire the PWM's up
    00589     sc->duty = 1023;
    00590
    00591     int pwm = index * 2;
    00592     Pwm_Set( pwm, sc->duty );
    00593     Pwm_Set( pwm + 1, sc->duty );
    00594
    00595     // Get IO's
    00596     int i;
    00597     for ( i = 0; i < 4; i++ )
    00598     {
    00599       int io = Stepper_GetIo( index, i );
    00600       sc->io[ i ] = io;
    00601
    00602       // Try to lock the stepper output
    00603       status = Io_Start( io, true );
    00604       if ( status != CONTROLLER_OK )
    00605       {
    00606         // Damn - unlock any that we did get
    00607         int j;
    00608         for ( j = 0; j < i; j++ )
    00609           Io_Stop( sc->io[ j ] );
    00610
    00611         Pwm_Stop( pwm );
    00612         Pwm_Stop( pwm + 1 );
    00613
    00614         Stepper->users--;
    00615         sc->users--;
    00616         return status;
    00617       }
    00618       Io_SetPio( io, true );
    00619       Io_SetValue( io, true );
    00620       Io_SetDirection( io, IO_OUTPUT );
    00621     }
    00622
    00623     DisableFIQFromThumb();
    00624     sc->position = 0;
    00625     sc->positionRequested = 0;
    00626     sc->speed = 10;
    00627     sc->timerRunning = 0;
    00628     sc->halfStep = false;
    00629     sc->bipolar = true;
    00630     EnableFIQFromThumb();
    00631
    00632     FastTimer_InitializeEntry( &sc->fastTimerEntry, Stepper_IRQCallback, index, sc->speed * 1000, true );
    00633     Stepper->users++;
    00634   }
    00635
    00636   return CONTROLLER_OK;
    00637 }
    00638
    00639 int Stepper_Stop( int index )
    00640 {
    00641   if ( index < 0 || index >= STEPPER_COUNT || Stepper == NULL )
    00642     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00643
    00644   if( Stepper->control[ index ] == NULL )
    00645     return CONTROLLER_OK;
    00646
    00647   StepperControl* s = Stepper->control[ index ];
    00648
    00649   if ( s->users <= 0 )
    00650     return CONTROLLER_ERROR_TOO_MANY_STOPS;
    00651
    00652   if ( --s->users == 0 )
    00653   {
    00654     if ( s->timerRunning )
    00655     {
    00656       DisableFIQFromThumb();
    00657       FastTimer_Cancel( &s->fastTimerEntry );
    00658       EnableFIQFromThumb();
    00659     }
    00660
    00661     int i;
    00662     for ( i = 0; i < 4; i++ )
    00663     {
    00664       int io = s->io[ i ];
    00665       Io_SetValue( io, false );
    00666       Io_Stop( io );
    00667     }
    00668
    00669     int pwm = index * 2;
    00670     Pwm_Stop( pwm );
    00671     Pwm_Stop( pwm + 1 );
    00672
    00673     Free( s );
    00674     s = NULL;
    00675
    00676     if ( --Stepper->users == 0 )
    00677     {
    00678       Free( Stepper );
    00679       Stepper = NULL;
    00680     }
    00681   }
    00682
    00683   return CONTROLLER_OK;
    00684 }
    00685
    00686
    00687 int Stepper_GetIo( int stepperIndex, int ioIndex )
    00688 {
    00689   int io = -1;
    00690   switch ( stepperIndex )
    00691   {
    00692     case 0:
    00693       switch ( ioIndex )
    00694       {
    00695         case 0:
    00696           io = STEPPER_0_IO_0;
    00697           break;
    00698         case 1:
    00699           io = STEPPER_0_IO_1;
    00700           break;
    00701         case 2:
    00702           io = STEPPER_0_IO_2;
    00703           break;
    00704         case 3:
    00705           io = STEPPER_0_IO_3;
    00706           break;
    00707       }
    00708       break;
    00709     case 1:
    00710       switch ( ioIndex )
    00711       {
    00712         case 0:
    00713           io = STEPPER_1_IO_0;
    00714           break;
    00715         case 1:
    00716           io = STEPPER_1_IO_1;
    00717           break;
    00718         case 2:
    00719           io = STEPPER_1_IO_2;
    00720           break;
    00721         case 3:
    00722           io = STEPPER_1_IO_3;
    00723           break;
    00724       }
    00725       break;
    00726   }
    00727   return io;
    00728 }
    00729
    00730 int Stepper_Init()
    00731 {
    00732   if( Stepper == NULL )
    00733   {
    00734     Stepper = MallocWait( sizeof( Stepper_ ), 100 );
    00735     Stepper->users = 0;
    00736     int i;
    00737     for( i = 0; i < STEPPER_COUNT; i++ )
    00738       Stepper->control[ i ] = NULL;
    00739   }
    00740   // otherwise, we're all set.
    00741   return CONTROLLER_OK;
    00742 }
    00743
    00744 void Stepper_IRQCallback( int id )
    00745 {
    00746   if(id < 0 || id > 1)
    00747     return;
    00748   StepperControl* s = Stepper->control[ id ];
    00749
    00750   if ( s->position < s->positionRequested )
    00751     s->position++;
    00752   if ( s->position > s->positionRequested )
    00753     s->position--;
    00754
    00755   if ( s->bipolar )
    00756   {
    00757     if ( s->halfStep )
    00758       Stepper_SetBipolarHalfStepOutput( s, s->position );
    00759     else
    00760       Stepper_SetBipolarOutput( s, s->position );
    00761   }
    00762   else
    00763   {
    00764     if ( s->halfStep )
    00765       Stepper_SetUnipolarHalfStepOutput( s, s->position );
    00766     else
    00767       Stepper_SetUnipolarOutput( s, s->position );
    00768   }
    00769
    00770   if ( s->position == s->positionRequested )
    00771   {
    00772     FastTimer_Cancel( &s->fastTimerEntry );
    00773     s->timerRunning = false;
    00774   }
    00775 }
    00776
    00777 void Stepper_SetDetails( StepperControl* s )
    00778 {
    00779   if ( !s->timerRunning && ( s->position != s->positionRequested ) && ( s->speed != 0 ) )
    00780   {
    00781     s->timerRunning = true;
    00782     DisableFIQFromThumb();
    00783     FastTimer_Set( &s->fastTimerEntry );
    00784     EnableFIQFromThumb();
    00785   }
    00786   else
    00787   {
    00788     if ( ( s->timerRunning ) && ( ( s->position == s->positionRequested ) || ( s->speed == 0 ) ) )
    00789     {
    00790       DisableFIQFromThumb();
    00791       FastTimer_Cancel( &s->fastTimerEntry );
    00792       EnableFIQFromThumb();
    00793       s->timerRunning = false;
    00794     }
    00795   }
    00796 }
    00797
    00798 void Stepper_SetUnipolarHalfStepOutput( StepperControl *s, int position )
    00799 {
    00800   //int output = position % 8;
    00801   int output = position & 0x7;
    00802
    00803   int* iop = s->io;
    00804
    00805   int portAOn = 0;
    00806   int portBOn = 0;
    00807   int portAOff = 0;
    00808   int portBOff = 0;
    00809
    00810   switch ( output )
    00811   {
    00812     case -1:
    00813       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00814       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00815       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00816       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00817       break;
    00818     case 0:
    00819       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00820       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00821       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00822       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00823       break;
    00824     case 1:
    00825       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00826       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00827       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00828       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00829       break;
    00830     case 2:
    00831       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00832       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00833       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00834       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00835       break;
    00836     case 3:
    00837       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00838       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00839       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00840       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00841       break;
    00842     case 4:
    00843       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00844       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00845       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00846       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00847       break;
    00848     case 5:
    00849       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00850       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00851       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00852       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00853       break;
    00854     case 6:
    00855       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00856       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00857       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00858       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00859       break;
    00860     case 7:
    00861       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00862       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00863       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00864       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00865       break;
    00866   }
    00867
    00868   Stepper_SetAll( portAOn, portBOn, portAOff, portBOff );
    00869 }
    00870
    00871 void Stepper_SetUnipolarOutput( StepperControl *s, int position )
    00872 {
    00873   //int output = position % 4;
    00874   int output = position & 0x3;
    00875   int* iop = s->io;
    00876
    00877   int portAOn = 0;
    00878   int portBOn = 0;
    00879   int portAOff = 0;
    00880   int portBOff = 0;
    00881
    00882   switch ( output )
    00883   {
    00884     case -1:
    00885       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00886       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00887       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00888       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00889       break;
    00890     case 0:
    00891       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00892       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00893       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00894       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00895       break;
    00896     case 1:
    00897       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00898       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00899       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00900       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00901       break;
    00902     case 2:
    00903       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00904       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00905       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00906       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00907       break;
    00908     case 3:
    00909       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00910       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00911       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00912       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00913       break;
    00914   }
    00915   Stepper_SetAll( portAOn, portBOn, portAOff, portBOff );
    00916 }
    00917
    00918 void Stepper_SetBipolarHalfStepOutput( StepperControl *s, int position )
    00919 {
    00920   //int output = position % 8;
    00921   int output = position & 0x7;
    00922   int* iop = s->io;
    00923
    00924   int portAOn = 0;
    00925   int portBOn = 0;
    00926   int portAOff = 0;
    00927   int portBOff = 0;
    00928
    00929   switch ( output )
    00930   {
    00931     case -1:
    00932       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00933       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00934       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00935       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00936       break;
    00937     case 0:
    00938       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00939       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00940       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00941       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00942       break;
    00943     case 1:
    00944       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00945       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00946       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00947       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00948       break;
    00949     case 2:
    00950       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00951       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00952       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00953       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00954       break;
    00955     case 3:
    00956       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00957       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00958       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00959       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00960       break;
    00961     case 4:
    00962       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00963       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00964       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00965       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00966       break;
    00967     case 5:
    00968       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00969       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00970       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00971       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00972       break;
    00973     case 6:
    00974       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00975       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00976       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00977       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00978       break;
    00979     case 7:
    00980       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00981       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00982       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    00983       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    00984       break;
    00985   }
    00986
    00987   Stepper_SetAll( portAOn, portBOn, portAOff, portBOff );
    00988 }
    00989
    00990 void Stepper_SetBipolarOutput( StepperControl *s, int position )
    00991 {
    00992   //int output = position % 4; // work around % bug - negative numbers not handled properly
    00993   int output = position & 0x3;
    00994   int* iop = s->io;
    00995
    00996   int portAOn = 0;
    00997   int portBOn = 0;
    00998   int portAOff = 0;
    00999   int portBOff = 0;
    01000
    01001   // This may be the least efficient code I have ever written
    01002   switch ( output )
    01003   {
    01004     case -1:
    01005       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    01006       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    01007       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    01008       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    01009       break;
    01010     case 0:
    01011       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    01012       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    01013       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    01014       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    01015       break;
    01016     case 1:
    01017       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    01018       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    01019       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    01020       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    01021       break;
    01022     case 2:
    01023       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    01024       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    01025       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    01026       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    01027       break;
    01028     case 3:
    01029       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    01030       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    01031       Stepper_SetOff( *iop++, &portAOff, &portBOff );
    01032       Stepper_SetOn( *iop++, &portAOn, &portBOn );
    01033       break;
    01034   }
    01035   Stepper_SetAll( portAOn, portBOn, portAOff, portBOff );
    01036 }
    01037
    01038 void Stepper_SetOn( int index, int* portAOn, int* portBOn )
    01039 {
    01040   int mask = 1 << ( index & 0x1F );
    01041   if ( index < 32 )
    01042     *portAOn |= mask;
    01043   else
    01044     *portBOn |= mask;
    01045 }
    01046
    01047 void Stepper_SetOff( int index, int* portAOff, int* portBOff )
    01048 {
    01049   int mask = 1 << ( index & 0x1F );
    01050   if ( index < 32 )
    01051     *portAOff |= mask;
    01052   else
    01053     *portBOff |= mask;
    01054 }
    01055
    01056 void Stepper_SetAll( int portAOn, int portBOn, int portAOff, int portBOff )
    01057 {
    01058   AT91C_BASE_PIOA->PIO_SODR = portAOn;
    01059   AT91C_BASE_PIOB->PIO_SODR = portBOn;
    01060   AT91C_BASE_PIOA->PIO_CODR = portAOff;
    01061   AT91C_BASE_PIOB->PIO_CODR = portBOff;
    01062 }
    01063
    01064 #ifdef OSC // defined in config.h
    01065
    01066 /** \defgroup StepperOSC Stepper - OSC
    01067   \ingroup OSC
    01068   Control Stepper motors with the Application Board via OSC.
    01069   Specify settings for your stepper motor by setting whether it's:
    01070   - bipolar or unipolar
    01071   - normal of half-stepping
    01072
    01073   You can generally use the stepper motor in 2 modes - \b absolute positioning or \b relative positioning.
    01074
    01075   For absolute positioning, set \b positionrequested with the desired position, and the motor will move there.
    01076   You can read back the stepper's \b position property at any point along the way to determine where it is at a given moment.  The board
    01077   keeps an internal count of how many steps the motor has taken in order to keep track of where it is.
    01078
    01079   For relative positioning, use the \b step property to simply move a number of steps from the current position.
    01080
    01081   \section devices Devices
    01082   There are 2 Stepper controllers available on the Application Board, numbered 0 & 1.
    01083   See the Stepper section in the Application Board user's guide for more information
    01084   on hooking steppers up to the board.
    01085
    01086   \section properties Properties
    01087   Each stepper controller has eight properties:
    01088   - position
    01089   - positionrequested
    01090   - speed
    01091   - duty
    01092   - bipolar
    01093   - halfstep
    01094   - step
    01095   - active
    01096
    01097   \par Step
    01098   The \b step property simply tells the motor to take a certain number of steps.
    01099   This is a write-only value.
    01100   \par
    01101   To take 1000 steps with the first stepper, send the message
    01102   \verbatim /stepper/0/step 1000\endverbatim
    01103
    01104   \par Position
    01105   The \b position property corresponds to the current step position of the stepper motor
    01106   This value can be both read and written.  Writing this value changes where the motor thinks it is.
    01107   The initial value of this parameter is 0.
    01108   \par
    01109   To set the first stepper to step position 10000, send the message
    01110   \verbatim /stepper/0/position 10000\endverbatim
    01111   Leave the argument value off to read the position of the stepper:
    01112   \verbatim /stepper/0/position \endverbatim
    01113
    01114   \par PositionRequested
    01115   The \b positionrequested property describes the desired step position of the stepper motor
    01116   This value can be both read and written.  Writing this value changes the motor's destination.
    01117   \par
    01118   To set the first stepper to go to position 10000, send the message
    01119   \verbatim /stepper/0/positionrequested 10000\endverbatim
    01120   Leave the argument value off to read the last requested position of the stepper:
    01121   \verbatim /stepper/0/positionrequested \endverbatim
    01122
    01123   \par Speed
    01124   The \b speed property corresponds to the speed with which the stepper responds to changes
    01125   of position.  This value is the number of milliseconds between each step.  So, a speed of one
    01126   would be a step every millisecond, or 1000 steps a second.
    01127   \par
    01128   Note that not all stepper motors can be stepped quite that fast.  If you find your stepper motor acting strangely,
    01129   experiment with slowing down the speed a bit.
    01130   \par
    01131   To set the speed of the first stepper to step at 100ms per step, send a message like
    01132   \verbatim /stepper/0/speed 100 \endverbatim
    01133   Adjust the argument value to one that suits your application.\n
    01134   Leave the argument value off to read the speed of the stepper:
    01135   \verbatim /stepper/0/speed \endverbatim
    01136
    01137   \par Duty
    01138   The \b duty property corresponds to the how much of the power supply is to be sent to the
    01139   stepper.  This is handy for when the stepper is static and not being required to perform too
    01140   much work and reducing its power helps reduce heat dissipation.
    01141   This value can be both read and written, and the range of values is 0 - 1023.  A duty of 0
    01142   means the stepper gets no power, and the value of 1023 means the stepper gets full power.
    01143   \par
    01144   To set the duty of the first stepper to 500, send a message like
    01145   \verbatim /stepper/0/duty 500 \endverbatim
    01146   Adjust the argument value to one that suits your application.\n
    01147   Leave the argument value off to read the duty of the stepper:
    01148   \verbatim /stepper/0/duty \endverbatim
    01149
    01150   \par Bipolar
    01151   The \b bipolar property is set to the style of stepper being used.  A value of 1 specifies bipolar
    01152   (the default) and 0 specifies a unipolar stepper.
    01153   This value can be both read and written.
    01154
    01155   \par HalfStep
    01156   The \b halfstep property controls whether the stepper is being half stepped or not.  A 0 here implies full stepping
    01157   (the default) and 1 implies a half stepping.
    01158   This value can be both read and written.
    01159
    01160   \par Active
    01161   The \b active property corresponds to the active state of the stepper.
    01162   If the stepper is set to be active, no other tasks will be able to
    01163   write to the same I/O lines.  If you're not seeing appropriate
    01164   responses to your messages to a stepper, check the whether it's
    01165   locked by sending a message like
    01166   \verbatim /stepper/1/active \endverbatim
    01167 */
    01168
    01169 #include "osc.h"
    01170 #include "string.h"
    01171 #include "stdio.h"
    01172
    01173 // Need a list of property names
    01174 // MUST end in zero
    01175 static char* StepperOsc_Name = "stepper";
    01176 static char* StepperOsc_PropertyNames[] = { "active", "position", "positionrequested",
    01177                                             "speed", "duty", "halfstep",
    01178                                             "bipolar", "step", 0 }; // must have a trailing 0
    01179
    01180 int StepperOsc_PropertySet( int index, int property, int value );
    01181 int StepperOsc_PropertyGet( int index, int property );
    01182
    01183 // Returns the name of the subsystem
    01184 const char* StepperOsc_GetName( )
    01185 {
    01186   return StepperOsc_Name;
    01187 }
    01188
    01189 // Now getting a message.  This is actually a part message, with the first
    01190 // part (the subsystem) already parsed off.
    01191 int StepperOsc_ReceiveMessage( int channel, char* message, int length )
    01192 {
    01193   int status = Osc_IndexIntReceiverHelper( channel, message, length,
    01194                                            STEPPER_COUNT, StepperOsc_Name,
    01195                                            StepperOsc_PropertySet, StepperOsc_PropertyGet,
    01196                                            StepperOsc_PropertyNames );
    01197
    01198   if ( status != CONTROLLER_OK )
    01199     return Osc_SendError( channel, StepperOsc_Name, status );
    01200   return CONTROLLER_OK;
    01201 }
    01202
    01203 // Set the index LED, property with the value
    01204 int StepperOsc_PropertySet( int index, int property, int value )
    01205 {
    01206   switch ( property )
    01207   {
    01208     case 0:
    01209       Stepper_SetActive( index, value );
    01210       break;
    01211     case 1:
    01212       Stepper_SetPosition( index, value );
    01213       break;
    01214     case 2:
    01215       Stepper_SetPositionRequested( index, value );
    01216       break;
    01217     case 3:
    01218       Stepper_SetSpeed( index, value );
    01219       break;
    01220     case 4:
    01221       Stepper_SetDuty( index, value );
    01222       break;
    01223     case 5:
    01224       Stepper_SetHalfStep( index, value );
    01225       break;
    01226     case 6:
    01227       Stepper_SetBipolar( index, value );
    01228       break;
    01229     case 7: // step
    01230       Stepper_Step( index, value );
    01231       break;
    01232   }
    01233   return CONTROLLER_OK;
    01234 }
    01235
    01236 // Get the index LED, property
    01237 int StepperOsc_PropertyGet( int index, int property )
    01238 {
    01239   int value = 0;
    01240   switch ( property )
    01241   {
    01242     case 0:
    01243       value = Stepper_GetActive( index );
    01244       break;
    01245     case 1:
    01246       value = Stepper_GetPosition( index );
    01247       break;
    01248     case 2:
    01249       value = Stepper_GetPositionRequested( index );
    01250       break;
    01251     case 3:
    01252       value = Stepper_GetSpeed( index );
    01253       break;
    01254     case 4:
    01255       value = Stepper_GetDuty( index );
    01256       break;
    01257     case 5:
    01258       value = Stepper_GetHalfStep( index );
    01259       break;
    01260     case 6:
    01261       value = Stepper_GetBipolar( index );
    01262       break;
    01263   }
    01264   return value;
    01265 }
    01266
    01267 #endif
    01268
    01269

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.