pwm.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. * Copyright 2008 by egnite GmbH
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. */
  32. /*!
  33. * \file arch/avr32/dev/pwm.c
  34. * \brief AVR32 Pulse Width Modulation.
  35. *
  36. * \verbatim
  37. * $Id: pwm.c,v 1.2 2008/10/03 11:30:22 haraldkipp Exp $
  38. * \endverbatim
  39. */
  40. #include <arch/avr32.h>
  41. #include <arch/avr32/gpio.h>
  42. #include <dev/gpio.h>
  43. #include <avr32/io.h>
  44. /*!
  45. * \addtogroup xgNutArchAvr32Pwm
  46. */
  47. /*@{*/
  48. static unsigned short FindClockConfiguration(unsigned int frequency, unsigned int mck)
  49. {
  50. unsigned char divisor = 0;
  51. unsigned int prescaler;
  52. NUTASSERT(frequency < mck);
  53. // Find prescaler and divisor values
  54. prescaler = (mck / _BV(divisor)) / frequency;
  55. while ((prescaler > 255) && (divisor < 11)) {
  56. divisor++;
  57. prescaler = (mck / _BV(divisor)) / frequency;
  58. }
  59. // Return result
  60. if (divisor < 11) {
  61. return prescaler | (divisor << 8);
  62. } else {
  63. return 0;
  64. }
  65. }
  66. /*!
  67. Configures PWM clocks A & B to run at the given frequencies.
  68. \param clka Desired clock A frequency (0 if not used).
  69. \param clkb Desired clock B frequency (0 if not used).
  70. */
  71. int NutPwmInit(unsigned int clka, unsigned int clkb)
  72. {
  73. unsigned int mode = 0;
  74. unsigned int result;
  75. unsigned int mck = NutClockGet(NUT_HWCLK_PERIPHERAL_A);
  76. // Clock A
  77. if (clka != 0) {
  78. result = FindClockConfiguration(clka, mck);
  79. NUTASSERT(result != 0);
  80. mode |= (result << AVR32_PWM_MR_DIVA_OFFSET);
  81. }
  82. // Clock B
  83. if (clkb != 0) {
  84. result = FindClockConfiguration(clkb, mck);
  85. NUTASSERT(result != 0);
  86. mode |= (result << AVR32_PWM_DIVB_OFFSET);
  87. }
  88. // Configure clocks
  89. AVR32_PWM.mr = mode;
  90. return 0;
  91. }
  92. /*!
  93. * \brief System reset.
  94. */
  95. int NutPwmChannelInit(unsigned int channel_id, unsigned int mode, unsigned int duty, unsigned int period)
  96. {
  97. NUTASSERT(channel_id <= AVR32_PWM_LINES_MSB);
  98. switch (channel_id )
  99. {
  100. case 0:
  101. GpioPinConfigSet( AVR32_GPIO_BANK(AVR32_PWM_0_PIN), AVR32_GPIO_PIN(AVR32_PWM_0_PIN), AVR32_GPIO_FUNCTION(AVR32_PWM_0_FUNCTION) );
  102. break;
  103. case 1:
  104. GpioPinConfigSet( AVR32_GPIO_BANK(AVR32_PWM_1_PIN), AVR32_GPIO_PIN(AVR32_PWM_1_PIN), AVR32_GPIO_FUNCTION(AVR32_PWM_1_FUNCTION) );
  105. break;
  106. case 2:
  107. GpioPinConfigSet( AVR32_GPIO_BANK(AVR32_PWM_2_PIN), AVR32_GPIO_PIN(AVR32_PWM_2_PIN), AVR32_GPIO_FUNCTION(AVR32_PWM_2_FUNCTION) );
  108. break;
  109. case 3:
  110. GpioPinConfigSet( AVR32_GPIO_BANK(AVR32_PWM_3_PIN), AVR32_GPIO_PIN(AVR32_PWM_3_PIN), AVR32_GPIO_FUNCTION(AVR32_PWM_3_FUNCTION) );
  111. break;
  112. case 4:
  113. GpioPinConfigSet( AVR32_GPIO_BANK(AVR32_PWM_4_1_PIN), AVR32_GPIO_PIN(AVR32_PWM_4_1_PIN), AVR32_GPIO_FUNCTION(AVR32_PWM_4_1_FUNCTION) );
  114. break;
  115. case 5:
  116. GpioPinConfigSet( AVR32_GPIO_BANK(AVR32_PWM_5_1_PIN), AVR32_GPIO_PIN(AVR32_PWM_5_1_PIN), AVR32_GPIO_FUNCTION(AVR32_PWM_5_1_FUNCTION) );
  117. break;
  118. case 6:
  119. GpioPinConfigSet( AVR32_GPIO_BANK(AVR32_PWM_6_PIN), AVR32_GPIO_PIN(AVR32_PWM_6_PIN), AVR32_GPIO_FUNCTION(AVR32_PWM_6_FUNCTION) );
  120. break;
  121. }
  122. AVR32_PWM.channel[channel_id].cmr = mode; // Channel mode.
  123. AVR32_PWM.channel[channel_id].cdty = duty; // Duty cycle, should be < CPRD.
  124. AVR32_PWM.channel[channel_id].cprd = period; // Channel period.
  125. return 0;
  126. }
  127. int NutPwmStartChannel(unsigned int channel)
  128. {
  129. AVR32_PWM.ena = _BV(channel);
  130. return 0;
  131. }
  132. int NutPwmStopChannel(unsigned int channel)
  133. {
  134. AVR32_PWM.dis = _BV(channel);
  135. return 0;
  136. }
  137. int NutPwmSetPeriod(unsigned int channel, unsigned short period)
  138. {
  139. AVR32_PWM.channel[channel].cprd = period;
  140. return 0;
  141. }
  142. int NutPwmSetDutyCycle(unsigned int channel, unsigned short duty)
  143. {
  144. AVR32_PWM.channel[channel].cdty = duty;
  145. return 0;
  146. }
  147. /*@}*/