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

- File List
- Globals

# pwmout.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 pwmout.c
    00021   PWM Out.
    00022   Library of functions for the Make Application Board's PwmOut Subsystem.
    00023 */
    00024
    00025 #include "pwmout.h"
    00026 #include "pwm.h"
    00027 #include "config.h"
    00028
    00029 #include "AT91SAM7X256.h"
    00030
    00031 #if ( APPBOARD_VERSION == 50 )
    00032   #define PWMOUT_0_IO_A IO_PA02
    00033   #define PWMOUT_0_IO_B IO_PA02
    00034   #define PWMOUT_1_IO_A IO_PA02
    00035   #define PWMOUT_1_IO_B IO_PA02
    00036   #define PWMOUT_2_IO_A IO_PA02
    00037   #define PWMOUT_2_IO_B IO_PA02
    00038   #define PWMOUT_3_IO_A IO_PA02
    00039   #define PWMOUT_3_IO_B IO_PA02
    00040 #endif
    00041 #if ( APPBOARD_VERSION == 90 )
    00042   #define PWMOUT_0_IO_A IO_PB23
    00043   #define PWMOUT_0_IO_B IO_PA26
    00044   #define PWMOUT_1_IO_A IO_PA25
    00045   #define PWMOUT_1_IO_B IO_PB25
    00046   #define PWMOUT_2_IO_A IO_PA02
    00047   #define PWMOUT_2_IO_B IO_PA06
    00048   #define PWMOUT_3_IO_A IO_PA05
    00049   #define PWMOUT_3_IO_B IO_PA24
    00050 #endif
    00051 #if ( APPBOARD_VERSION == 95 || APPBOARD_VERSION == 100 )
    00052   #define PWMOUT_0_IO_A IO_PA24
    00053   #define PWMOUT_0_IO_B IO_PA05
    00054   #define PWMOUT_1_IO_A IO_PA06
    00055   #define PWMOUT_1_IO_B IO_PA02
    00056   #define PWMOUT_2_IO_A IO_PB25
    00057   #define PWMOUT_2_IO_B IO_PA25
    00058   #define PWMOUT_3_IO_A IO_PA26
    00059   #define PWMOUT_3_IO_B IO_PB23
    00060 #endif
    00061
    00062 #define PWMOUT_COUNT 4
    00063
    00064 static int PwmOut_Start( int motor );
    00065 static int PwmOut_Stop( int motor );
    00066
    00067 static int PwmOut_users[ PWMOUT_COUNT ];
    00068
    00069 static void PwmOut_GetIos( int index, int* ioA, int* ioB );
    00070
    00071 /** \defgroup PwmOut PWM Out
    00072   The PWM Out subsystem underlies the DC Motor subsystem and controls the 4 PWM signals on the SAM7X.
    00073   Each PWM device controls a pair of Digital Outs - an A and a B channel:
    00074   - PwmOut 0 - Digital Outs 0 (A) and 1 (B).
    00075   - PwmOut 1 - Digital Outs 2 (A) and 3 (B).
    00076   - PwmOut 2 - Digital Outs 4 (A) and 5 (B).
    00077   - PwmOut 3 - Digital Outs 6 (A) and 7 (B).
    00078
    00079   The A and B channels of a PWM device can be set independently to be inverted, or not, from one another
    00080   in order to control motors, lights, etc.
    00081
    00082   The simplest way to get started is simply with a call to PwmOut_SetActive() and then to
    00083   PwmOut_SetDuty() - this will allow you to control simple dimming and motors.  If you need to adjust timing,
    00084   inversion or other parameters, delve a bit deeper into the API above.
    00085
    00086   PwmOut relies on the internal \ref Pwm system.  See that page for more info on the timing issues
    00087   involved with the PWM Out system.
    00088   \ingroup Libraries
    00089   @{
    00090 */
    00091
    00092 /**
    00093   Sets whether the specified PWM device is active.
    00094   @param index An integer specifying which PWM device (0-3).
    00095   @param state An integer specifying the active state - 1 (active) or 0 (inactive).
    00096   @return Zero on success.
    00097 */
    00098 int PwmOut_SetActive( int index, int state )
    00099 {
    00100   if ( index < 0 || index >= PWMOUT_COUNT )
    00101     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00102
    00103   if ( state )
    00104     return PwmOut_Start( index );
    00105   else
    00106     return PwmOut_Stop( index );
    00107 }
    00108
    00109 /**
    00110   Returns the active state of the LED.
    00111   @param index An integer specifying which PWM device (0-3).
    00112   @return Zero on success.
    00113 */
    00114 int PwmOut_GetActive( int index )
    00115 {
    00116   if ( index < 0 || index >= PWMOUT_COUNT )
    00117     return false;
    00118   return PwmOut_users[ index ] > 0;
    00119 }
    00120
    00121 /**
    00122   Set the speed of a PWM device.
    00123   @param index An integer specifying which PWM device (0-3).
    00124   @param duty An integer (0 - 1023) specifying the duty.
    00125   @return Zero on success.
    00126 */
    00127 int PwmOut_SetDuty( int index, int duty )
    00128 {
    00129   if ( index < 0 || index > 3 )
    00130     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00131
    00132   if ( PwmOut_users[ index ] < 1 )
    00133   {
    00134     int status = PwmOut_Start( index );
    00135     if ( status != CONTROLLER_OK )
    00136       return status;
    00137   }
    00138
    00139   return Pwm_Set( index, duty );
    00140 }
    00141
    00142 /**
    00143   Read the current duty of a PWM device.
    00144   @param index An integer specifying which PWM device (0-3).
    00145   @return The duty (0 - 1023).
    00146 */
    00147 int PwmOut_GetDuty( int index )
    00148 {
    00149   if ( index < 0 || index > 3 )
    00150     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00151
    00152   if ( PwmOut_users[ index ] < 1 )
    00153   {
    00154     int status = PwmOut_Start( index );
    00155     if ( status != CONTROLLER_OK )
    00156       return status;
    00157   }
    00158
    00159   return Pwm_Get( index );
    00160 }
    00161
    00162 /**
    00163   Set whether the A channel associated with a PWM out should be inverted.
    00164   @param index An integer specifying which PWM device (0-3).
    00165   @param invert A character specifying the inversion - 1/non-zero (inverted) 0 (normal).
    00166   @return Zero on success.
    00167 */
    00168 int PwmOut_SetInvertA( int index, char invert )
    00169 {
    00170   if ( index < 0 || index > 3 )
    00171     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00172
    00173   if ( PwmOut_users[ index ] < 1 )
    00174   {
    00175     int status = PwmOut_Start( index );
    00176     if ( status != CONTROLLER_OK )
    00177       return status;
    00178   }
    00179
    00180   // Look up the IO that are involved
    00181   int ioA;
    00182   int ioB;
    00183   PwmOut_GetIos( index, &ioA, &ioB );
    00184
    00185   Io_SetValue( ioA, !invert );
    00186
    00187   return CONTROLLER_OK;
    00188 }
    00189
    00190 /**
    00191   Read whether the A channel of a PWM device is inverted.
    00192   @param index An integer specifying which PWM device (0-3).
    00193   @return The inversion - 1/non-zero (inverted) or 0 (normal).
    00194 */
    00195 int PwmOut_GetInvertA( int index )
    00196 {
    00197   if ( index < 0 || index > 3 )
    00198     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00199
    00200   if ( PwmOut_users[ index ] < 1 )
    00201   {
    00202     int status = PwmOut_Start( index );
    00203     if ( status != CONTROLLER_OK )
    00204       return status;
    00205   }
    00206
    00207   // Look up the IO that are involved
    00208   int ioA;
    00209   int ioB;
    00210   PwmOut_GetIos( index, &ioA, &ioB );
    00211
    00212   return Io_GetValue( ioA );
    00213 }
    00214
    00215 /**
    00216   Read whether the B channel of a PWM out is inverted.
    00217   @param index An integer specifying which PWM device (0-3).
    00218   @param invert A character specifying the inversion - 1/non-zero (inverted) 0 (normal).
    00219   @return Zero on success.
    00220 */
    00221 int PwmOut_SetInvertB( int index, char invert )
    00222 {
    00223   if ( index < 0 || index > 3 )
    00224     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00225
    00226   if ( PwmOut_users[ index ] < 1 )
    00227   {
    00228     int status = PwmOut_Start( index );
    00229     if ( status != CONTROLLER_OK )
    00230       return status;
    00231   }
    00232
    00233   // Look up the IO that are involved
    00234   int ioA;
    00235   int ioB;
    00236   PwmOut_GetIos( index, &ioA, &ioB );
    00237
    00238   Io_SetValue( ioB, !invert );
    00239
    00240   return CONTROLLER_OK;
    00241 }
    00242
    00243 /**
    00244   Read whether the B channel of a PWM device is inverted.
    00245   @param index An integer specifying which PWM device (0-3).
    00246   @return The inversion - 1/non-zero (inverted) or 0 (normal).
    00247 */
    00248 int PwmOut_GetInvertB( int index )
    00249 {
    00250   if ( index < 0 || index > 3 )
    00251     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00252
    00253   if ( PwmOut_users[ index ] < 1 )
    00254   {
    00255     int status = PwmOut_Start( index );
    00256     if ( status != CONTROLLER_OK )
    00257       return status;
    00258   }
    00259
    00260   // Look up the IO that are involved
    00261   int ioA;
    00262   int ioB;
    00263   PwmOut_GetIos( index, &ioA, &ioB );
    00264
    00265   return Io_GetValue( ioB );
    00266 }
    00267
    00268
    00269 /**
    00270   Set whether the 2 channels of a PWM device are inverted.
    00271   This is a convenience function, and is equivalent to making separate calls to PwmOut_SetInvertA() and PwmOut_SetInvertB().
    00272   @param index An integer specifying which PWM device (0-3).
    00273   @param invertA A character specifying the inversion of the A channel - 1/non-zero (inverted) or 0 (normal).
    00274   @param invertB A character specifying the inversion of the B channel - 1/non-zero (inverted) or 0 (normal).
    00275   @return Zero on success.
    00276 */
    00277 int PwmOut_SetInvert( int index, char invertA, char invertB )
    00278 {
    00279   if ( index < 0 || index > 3 )
    00280     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00281
    00282   if ( PwmOut_users[ index ] < 1 )
    00283   {
    00284     int status = PwmOut_Start( index );
    00285     if ( status != CONTROLLER_OK )
    00286       return status;
    00287   }
    00288
    00289   // Look up the IO that are involved
    00290   int ioA;
    00291   int ioB;
    00292   PwmOut_GetIos( index, &ioA, &ioB );
    00293
    00294   Io_SetValue( ioA, !invertA );
    00295   Io_SetValue( ioB, !invertB );
    00296
    00297   return CONTROLLER_OK;
    00298 }
    00299
    00300 /**
    00301   Set the duty and the inversion of both channels of a PWM device.
    00302   This is a convenience function to set all the properties of a PWM device in a single call.\n
    00303   It is equivalent to separate calls to PwmOut_SetInvert() and PwmOut_SetDuty().
    00304   @param index An integer specifying which PWM out.
    00305   @param duty An integer specifying the duty (0 - 1023).
    00306   @param invertA A character specifying the inversion of the A channel - 1/non-zero (inverted) or 0 (normal).
    00307   @param invertB A character specifying the inversion of the B channel - 1/non-zero (inverted) or 0 (normal).
    00308   @return Zero on success
    00309 */
    00310 int PwmOut_SetAll( int index, int duty, char invertA, char invertB )
    00311 {
    00312   if ( index < 0 || index > 3 )
    00313     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00314
    00315   if ( PwmOut_users[ index ] < 1 )
    00316   {
    00317     int status = PwmOut_Start( index );
    00318     if ( status != CONTROLLER_OK )
    00319       return status;
    00320   }
    00321
    00322   // Look up the IO that are involved
    00323   int ioA;
    00324   int ioB;
    00325   PwmOut_GetIos( index, &ioA, &ioB );
    00326
    00327   Io_SetValue( ioA, !invertA );
    00328   Io_SetValue( ioB, !invertB );
    00329
    00330   return Pwm_Set( index, duty );;
    00331 }
    00332
    00333 int PwmOut_Start( int index )
    00334 {
    00335   int status;
    00336
    00337   if ( index < 0 || index > 3 )
    00338     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00339
    00340   if ( PwmOut_users[ index ]++ == 0 )
    00341   {
    00342     // Look up the IO's that will be used
    00343     int ioA;
    00344     int ioB;
    00345     PwmOut_GetIos( index, &ioA, &ioB );
    00346
    00347     // Try to get the IO's
    00348     status = Io_Start( ioA, true );
    00349     if ( status != CONTROLLER_OK )
    00350     {
    00351       PwmOut_users[ index ]--;
    00352       return status;
    00353     }
    00354
    00355     status = Io_Start( ioB, true );
    00356     if ( status != CONTROLLER_OK )
    00357     {
    00358       PwmOut_users[ index ]--;
    00359       // better give back ioA since we did get that
    00360       Io_Stop( ioA );
    00361       return status;
    00362     }
    00363
    00364     // Make sure we can get the PWM channel
    00365     status = Pwm_Start( index );
    00366     if ( status != CONTROLLER_OK )
    00367     {
    00368       PwmOut_users[ index ]--;
    00369       // better give back the io's since we did get them
    00370       Io_Stop( ioA );
    00371       Io_Stop( ioB );
    00372       return status;
    00373     }
    00374
    00375     // Set all the io's right
    00376
    00377     // Enable as PIOs
    00378     Io_SetPio( ioA, true );
    00379     Io_SetPio( ioB, true );
    00380
    00381     // Switch them off
    00382     Io_SetValue( ioA, false );
    00383     Io_SetValue( ioB, false );
    00384
    00385     // Turn them into outputs
    00386     Io_SetDirection( ioA, IO_OUTPUT );
    00387     Io_SetDirection( ioB, IO_OUTPUT );
    00388
    00389     PwmOut_SetDuty( index, 0 );
    00390     Io_SetValue( ioA, true );
    00391   }
    00392
    00393   return CONTROLLER_OK;
    00394 }
    00395
    00396 int PwmOut_Stop( int index )
    00397 {
    00398   if ( index < 0 || index > 3 )
    00399     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00400
    00401   if ( PwmOut_users[ index ] <= 0 )
    00402     return CONTROLLER_ERROR_NOT_LOCKED;
    00403
    00404   if ( --PwmOut_users[ index ] == 0 )
    00405   {
    00406     // Look up the IO's that are involved
    00407     int ioA;
    00408     int ioB;
    00409     PwmOut_GetIos( index, &ioA, &ioB );
    00410
    00411     // Turn them off
    00412     Io_SetValue( ioA, false );
    00413     Io_SetValue( ioB, false );
    00414
    00415     Io_Stop( ioA );
    00416     Io_Stop( ioB );
    00417
    00418     Pwm_Stop( index );
    00419   }
    00420
    00421   return CONTROLLER_OK;
    00422 }
    00423
    00424 void PwmOut_GetIos( int index, int* ioA, int* ioB )
    00425 {
    00426   switch ( index )
    00427   {
    00428     case 0:
    00429       *ioA = PWMOUT_0_IO_A;
    00430       *ioB = PWMOUT_0_IO_B;
    00431       break;
    00432     case 1:
    00433       *ioA = PWMOUT_1_IO_A;
    00434       *ioB = PWMOUT_1_IO_B;
    00435       break;
    00436     case 2:
    00437       *ioA = PWMOUT_2_IO_A;
    00438       *ioB = PWMOUT_2_IO_B;
    00439       break;
    00440     case 3:
    00441       *ioA = PWMOUT_3_IO_A;
    00442       *ioB = PWMOUT_3_IO_B;
    00443       break;
    00444     default:
    00445       *ioA = 0;
    00446       *ioB = 0;
    00447       break;
    00448   }
    00449 }
    00450
    00451 /**
    00452   Set the divider A value.
    00453   Contributed by TheStigg - http://www.makingthings.com/author/thestigg
    00454   @param val The value (between 0 and 255)
    00455   @return 0 on success.
    00456 */
    00457 int PwmOut_SetDividerAValue(int val)
    00458 {
    00459    if( val < 0 || val > 255 )
    00460     return CONTROLLER_ERROR_ILLEGAL_PARAMETER_VALUE;
    00461
    00462    int v = Pwm_GetDividerA();
    00463
    00464    //strip off the divider Value
    00465    v &= 0x00000f00;
    00466
    00467    //add on the new Value
    00468    v |= val;
    00469
    00470    return Pwm_SetDividerA( v );
    00471 }
    00472
    00473 /**
    00474   Read the divider A value.
    00475   Contributed by TheStigg - http://www.makingthings.com/author/thestigg
    00476   @return the divider A value (0 - 255)
    00477   @see PwmOut_SetDividerAValue( )
    00478 */
    00479 int PwmOut_GetDividerAValue()
    00480 {
    00481   return ( Pwm_GetDividerA() & 0x000000ff );
    00482 }
    00483
    00484 /**
    00485   Set the divider A mux value.
    00486   @param mux The mux value (between 0 and 10)
    00487   Contributed by TheStigg - http://www.makingthings.com/author/thestigg
    00488   @return 0 on success.
    00489 */
    00490 int PwmOut_SetDividerAMux(int mux)
    00491 {
    00492    if( mux < 0 || mux > 10 )
    00493     return CONTROLLER_ERROR_ILLEGAL_PARAMETER_VALUE;
    00494
    00495    int v = Pwm_GetDividerA();
    00496
    00497    //strip off the divider Value
    00498    v &= 0x000000ff;
    00499
    00500    //add on the new Value
    00501    v |= ( mux << 8 );
    00502
    00503    return Pwm_SetDividerA( v );
    00504 }
    00505 /**
    00506   Read the divider A mux value.
    00507   Contributed by TheStigg - http://www.makingthings.com/author/thestigg
    00508   @return the divider A mux value (0 - 10)
    00509   @see PwmOut_SetDividerAMux( )
    00510 */
    00511 int PwmOut_GetDividerAMux()
    00512 {
    00513   return ( ( Pwm_GetDividerA() >> 8 ) & 0x0000000f );
    00514 }
    00515
    00516 /**
    00517   Set the divider B value.
    00518   Contributed by TheStigg - http://www.makingthings.com/author/thestigg
    00519   @param val The value (between 0 and 255)
    00520   @return 0 on success.
    00521 */
    00522 int PwmOut_SetDividerBValue(int val)
    00523 {
    00524    if( val < 0 || val > 255 )
    00525     return CONTROLLER_ERROR_ILLEGAL_PARAMETER_VALUE;
    00526
    00527    int v = Pwm_GetDividerB();
    00528
    00529    //strip off the divider Value
    00530    v &= 0x00000f00;
    00531
    00532    //add on the new Value
    00533    v |= val;
    00534
    00535    return Pwm_SetDividerA( v );
    00536 }
    00537
    00538 /**
    00539   Read the divider B value.
    00540   Contributed by TheStigg - http://www.makingthings.com/author/thestigg
    00541   @return the divider B value (0 - 255)
    00542   @see PwmOut_SetDividerBValue( )
    00543 */
    00544 int PwmOut_GetDividerBValue()
    00545 {
    00546   return ( Pwm_GetDividerB() & 0x000000ff );
    00547 }
    00548
    00549 /**
    00550   Set the divider B mux value.
    00551   @param mux The mux value (between 0 and 10)
    00552   Contributed by TheStigg - http://www.makingthings.com/author/thestigg
    00553   @return 0 on success.
    00554 */
    00555 int PwmOut_SetDividerBMux(int mux)
    00556 {
    00557    if( mux < 0 || mux > 10 )
    00558     return CONTROLLER_ERROR_ILLEGAL_PARAMETER_VALUE;
    00559
    00560    int v = Pwm_GetDividerB();
    00561
    00562    //strip off the divider Value
    00563    v &= 0x000000ff;
    00564
    00565    //add on the new Value
    00566    v |= ( mux << 8 );
    00567
    00568    return Pwm_SetDividerB( v );
    00569 }
    00570
    00571 /**
    00572   Read the divider B mux value.
    00573   Contributed by TheStigg - http://www.makingthings.com/author/thestigg
    00574   @return the divider B mux value (0 - 10)
    00575   @see PwmOut_SetDividerBMux( )
    00576 */
    00577 int PwmOut_GetDividerBMux()
    00578 {
    00579   return ( ( Pwm_GetDividerB() >> 8 ) & 0x0000000f );
    00580 }
    00581
    00582 /**
    00583   Set the alignment of a channel's waveform.
    00584   Valid values are:
    00585   - 0 = Left Aligned (default)
    00586   - 1 = Center Aligned
    00587
    00588   Contributed by TheStigg - http://www.makingthings.com/author/thestigg
    00589   @param index The PWM channel (0-3) that you'd like to configure.
    00590   @param val The alignment value, as described above.
    00591   @return 0 on success.
    00592 */
    00593 int PwmOut_SetWaveformAlignment(int index, int val)
    00594 {
    00595   if ( index < 0 || index > 3 )
    00596     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00597   if ( val > 1 || val < 0 )
    00598     return CONTROLLER_ERROR_ILLEGAL_PARAMETER_VALUE;
    00599
    00600   int currval = Pwm_GetWaveformProperties( index ) & 0x00000006; //Leave bits 2 & 3 alone
    00601   currval |= val;
    00602   return Pwm_SetWaveformProperties( index, currval );
    00603 }
    00604
    00605 /**
    00606   Read the configured waveform alignment for a given PWM channel.
    00607
    00608   Contributed by TheStigg - http://www.makingthings.com/author/thestigg
    00609   @param index The PWM channel (0-3) you'd like to read from.
    00610   @return the waveform alignment - see PwmOut_SetWaveformAlignment( )
    00611 */
    00612 int PwmOut_GetWaveformAlignment( int index )
    00613 {
    00614   int val = Pwm_GetWaveformProperties( index );
    00615   if ( val < 0 )
    00616     return val;
    00617
    00618   return val  & 0x00000001;
    00619 }
    00620
    00621 /**
    00622   Set the Waveform Polarity for a PWM channel.
    00623   Valid values are:
    00624    - 0 = Start Waveform Low
    00625    - 1 = Start Waveform High (default)
    00626
    00627   Contributed by TheStigg - http://www.makingthings.com/author/thestigg
    00628   @param index The PWM channel (0-3) that you'd like to configure.
    00629   @param val The value, as described above.
    00630   @return 0 on success.
    00631 */
    00632 int PwmOut_SetWaveformPolarity(int index, int val)
    00633 {
    00634   if ( index < 0 || index > 3 )
    00635     return CONTROLLER_ERROR_ILLEGAL_INDEX;
    00636   if ( val > 1 || val < 0 )
    00637     return CONTROLLER_ERROR_ILLEGAL_PARAMETER_VALUE;
    00638
    00639   int currval = Pwm_GetWaveformProperties( index ) & 0x00000005; //Leave bits 3 & 1 alone
    00640   currval |= (val << 1);
    00641   return Pwm_SetWaveformProperties( index, currval );
    00642 }
    00643
    00644 /**
    00645   Read the waveform polarity for a given channel.
    00646
    00647   Contributed by TheStigg - http://www.makingthings.com/author/thestigg
    00648   @param index The PWM channel (0-3) that you'd like to read from.
    00649   @return The configured polarity for that channel.
    00650   @see PwmOut_SetWaveformPolarity( )
    00651 */
    00652 int PwmOut_GetWaveformPolarity( int index )
    00653 {
    00654   int val = Pwm_GetWaveformProperties( index );
    00655   if ( val < 0 )
    00656     return val;
    00657
    00658   return val  & 0x00000002;
    00659 }
    00660
    00661 /** @}
    00662 */
    00663
    00664 #ifdef OSC
    00665
    00666 /** \defgroup pwmout_osc PWM Out - OSC
    00667   Generate PWM signals with the Application Board via OSC.
    00668   \ingroup OSC
    00669
    00670   \section devices Devices
    00671   There are 4 PWM controllers available on the Application Board, numbered 0 - 3.
    00672
    00673   Each PWM Out controls a pair of Digital Outs - an A and a B channel:
    00674   - PwmOut 0 - Digital Outs 0 (A) and 1 (B).
    00675   - PwmOut 1 - Digital Outs 2 (A) and 3 (B).
    00676   - PwmOut 2 - Digital Outs 4 (A) and 5 (B).
    00677   - PwmOut 3 - Digital Outs 6 (A) and 7 (B).
    00678
    00679   Each channel can also be set to invert the given PWM signal.
    00680
    00681   \section properties Properties
    00682   Each PWM Out has the following properties:
    00683   - duty
    00684   - invA
    00685   - invB
    00686   - active
    00687   - dividerAValue
    00688   - dividerAMux
    00689   - dividerBValue
    00690   - dividerBMux
    00691   - clockSource
    00692   - alignment
    00693   - polarity
    00694
    00695   \subsection Duty
    00696   The \b duty property corresponds to the duty at which a load connected to the output is being driven.
    00697   This value can be both read and written.  The range of values expected by the board
    00698   is from 0 - 1023.
    00699
    00700   To generate a 75% on PWM signal, send a message like
    00701   \verbatim /pwmout/1/duty 768 \endverbatim
    00702   Leave the argument value off to read the duty:
    00703   \verbatim /pwmout/1/duty \endverbatim
    00704
    00705   \subsection invA
    00706   The \b invA property corresponds to the inversion of the A channel of a PWM Out.
    00707   This value can be both read and written, and the range of values expected is simply
    00708   0 or 1.  1 means inverted and 0 means normal.  0 is the default.
    00709
    00710   To set the A channel of the second PWM Out as inverted, send the message
    00711   \verbatim /pwmout/1/invA 1 \endverbatim
    00712   Note that the A channel of PWM Out 1 is Digital Out 2.
    00713
    00714   \subsection invB
    00715   The \b invB property corresponds to the inversion of the B channel of a PWM Out.
    00716   This value can be both read and written, and the range of values expected is simply
    00717   0 or 1.  1 means inverted and 0 means normal.  0 is the default.
    00718
    00719   To set the B channel of the fourth PWM Out back to normal, send the message
    00720   \verbatim /pwmout/1/invB 0 \endverbatim
    00721   Note that the A channel of PWM Out 1 is Digital Out 7.
    00722
    00723   \subsection Active
    00724   The \b active property corresponds to the active state of the PWM Out.
    00725   If the device is set to be active, no other tasks will be able to
    00726   use its 2 digital out lines.  If you're not seeing appropriate
    00727   responses to your messages to the PWM Out, check the whether it's
    00728   locked by sending a message like
    00729   \verbatim /pwmout/0/active \endverbatim
    00730
    00731   If you're no longer using the PWM Out, it's a good idea to free the 2 Digital Outs by
    00732   sending the message
    00733   \verbatim /pwmout/0/active 0 \endverbatim
    00734
    00735   \section p_adjust Period adjustment of the PWM unit
    00736
    00737   The below values allow you to adjust the period length to all possible values as supported
    00738   by the physical limits of the Make Controller.  Before altering the values, it is good to understand
    00739   a little about the subsustem of the PWM module.  Please see the general introduction in the \ref Pwm section.
    00740
    00741   \subsection DividerBValue
    00742   The \b dividerXValue property corresponds to the linear divider value within clock divider module X of the
    00743   PWM Out.  This value can be between 0 and 255, and linearly divides the clock that is fed into it.  You can
    00744   change the incomming clock value by altering the DividerAMux parameter.  Higher linear divider values mean
    00745   a longer period.
    00746
    00747   Default value of DividerA is 4. Default value of DividerB is 0.
    00748
    00749   \subsection divs DividerAMux & DividerBMux
    00750   The \b dividerAMux and \b dividerBMux properties select the incoming clock value for divider module A or B (respectively)
    00751   of the PWM Out.  This value ranges between 0 and 10.  This is similar to the clock source value, eg. a DividerAMux
    00752   value of 5 = a clock rate of MasterClock/(2^5)
    00753
    00754   Increasing this value will substantially increase the period of the PWM.  Use the DividerXValue parameter
    00755   to more finely tune the value of the period.
    00756
    00757   Default value of MuxA is 4.  Default value of MuxB is 0.
    00758
    00759   \subsection ClockSource
    00760   The \b clockSource property selects the incoming clock value for the specified PWM channel. A clock
    00761   source of \b 0-10 represents the Master clock divided by 2 to the power of the Clock Source Value, eg. a clock
    00762   source value of 5 = a clock rate of MasterClock/(2^5).  A value of \b 11 sets the Clock source to be
    00763   generated by clock Divider A.  A value of \b 12 sets the Clock source to be generated by clock Divider B
    00764
    00765   The default value is 11 (Divider A).
    00766
    00767   \subsection WaveformAlignment
    00768   The \b waveformAlignment property chooses whether the channel is left aligned or center aligned.
    00769   The following values are valid:
    00770    - 0 = Left aligned
    00771    - 1 = Center aligned
    00772
    00773   A left aligned channel counts up to the maximum duty cycle, then resets the counter.  A center aligned
    00774   channel counts up to the maximum duty cycle, then counts down to zero, etc. The default is left aligned.
    00775
    00776   \subsection WaveformPolarity
    00777   The \b polarity property chooses whether the channel begins its period high or low.  The following values are valid:
    00778    - 0 = Normal Polarity
    00779    - 1 = Inverted Polarity
    00780
    00781   Normal polarity starts low, then goes high.  Inverted polarity starts high, then goes low.  The default is inverted polarity.
    00782 */
    00783
    00784 #include "osc.h"
    00785 #include "string.h"
    00786 #include "stdio.h"
    00787
    00788 // Need a list of property names
    00789 // MUST end in zero
    00790 static char* PwmOutOsc_Name = "pwmout";
    00791 static char* PwmOutOsc_PropertyNames[] = { "active", "duty", "invA", "invB",
    00792              "dividerAValue", "dividerAMux",
    00793              "dividerBValue", "dividerBMux",
    00794              "clockSource", "alignment",
    00795              "polarity",
    00796              0 }; // must have a trailing 0
    00797
    00798 int PwmOutOsc_PropertySet( int index, int property, int value );
    00799 int PwmOutOsc_PropertyGet( int index, int property );
    00800
    00801 // Returns the name of the subsystem
    00802 const char* PwmOutOsc_GetName( )
    00803 {
    00804   return PwmOutOsc_Name;
    00805 }
    00806
    00807 // Now getting a message.  This is actually a part message, with the first
    00808 // part (the subsystem) already parsed off.
    00809 int PwmOutOsc_ReceiveMessage( int channel, char* message, int length )
    00810 {
    00811   int status = Osc_IndexIntReceiverHelper( channel, message, length,
    00812                                      PWMOUT_COUNT, PwmOutOsc_Name,
    00813                                      PwmOutOsc_PropertySet, PwmOutOsc_PropertyGet,
    00814                                      PwmOutOsc_PropertyNames );
    00815
    00816   if ( status != CONTROLLER_OK )
    00817     return Osc_SendError( channel, PwmOutOsc_Name, status );
    00818   return CONTROLLER_OK;
    00819 }
    00820
    00821 // Set the index LED, property with the value
    00822 int PwmOutOsc_PropertySet( int index, int property, int value )
    00823 {
    00824   switch ( property )
    00825   {
    00826     case 0:
    00827       PwmOut_SetActive( index, value );
    00828       break;
    00829     case 1:
    00830       PwmOut_SetDuty( index, value );
    00831       break;
    00832     case 2:
    00833       PwmOut_SetInvertA( index, value );
    00834       break;
    00835     case 3:
    00836       PwmOut_SetInvertB( index, value );
    00837       break;
    00838     case 4:
    00839       PwmOut_SetDividerAValue(value);
    00840       break;
    00841     case 5:
    00842       PwmOut_SetDividerAMux(value);
    00843       break;
    00844     case 6:
    00845       PwmOut_SetDividerBValue(value);
    00846       break;
    00847     case 7:
    00848       PwmOut_SetDividerBMux(value);
    00849       break;
    00850     case 8:
    00851       Pwm_SetClockSource( index, value );
    00852       break;
    00853     case 9:
    00854       PwmOut_SetWaveformAlignment( index, value );
    00855       break;
    00856     case 10:
    00857       PwmOut_SetWaveformPolarity( index, value );
    00858       break;
    00859   }
    00860   return CONTROLLER_OK;
    00861 }
    00862
    00863 // Get the index LED, property
    00864 int PwmOutOsc_PropertyGet( int index, int property )
    00865 {
    00866   int value = 0;
    00867   switch ( property )
    00868   {
    00869     case 0:
    00870       value = PwmOut_GetActive( index );
    00871       break;
    00872     case 1:
    00873       value = PwmOut_GetDuty( index );
    00874       break;
    00875     case 2:
    00876       value = PwmOut_GetInvertA( index );
    00877       break;
    00878     case 3:
    00879       value = PwmOut_GetInvertB( index );
    00880       break;
    00881     case 4:
    00882       value = PwmOut_GetDividerAValue();
    00883       break;
    00884     case 5:
    00885       value = PwmOut_GetDividerAMux();
    00886       break;
    00887     case 6:
    00888       value = PwmOut_GetDividerBValue();
    00889       break;
    00890     case 7:
    00891       value = PwmOut_GetDividerBMux();
    00892       break;
    00893     case 8:
    00894       value = Pwm_GetClockSource( index );
    00895       break;
    00896     case 9:
    00897       value = PwmOut_GetWaveformAlignment( index );
    00898       break;
    00899     case 10:
    00900       value = PwmOut_GetWaveformPolarity( index );
    00901       break;
    00902   }
    00903   return value;
    00904 }
    00905
    00906
    00907 #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.