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.