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