pwm.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. /* Copyright 2018 Canaan Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. #include <stddef.h>
  16. #include "io.h"
  17. #include "plic.h"
  18. #include "pwm.h"
  19. #include "sysctl.h"
  20. #include "timer.h"
  21. #include "utils.h"
  22. void pwm_init(pwm_device_number_t pwm_number)
  23. {
  24. sysctl_clock_enable(SYSCTL_CLOCK_TIMER0 + pwm_number);
  25. }
  26. void pwm_set_enable(pwm_device_number_t pwm_number, pwm_channel_number_t channel, int enable)
  27. {
  28. if(enable)
  29. {
  30. if(timer[pwm_number]->channel[channel].load_count == 0)
  31. timer[pwm_number]->channel[channel].load_count = 1;
  32. if(timer[pwm_number]->load_count2[channel] == 0)
  33. timer[pwm_number]->load_count2[channel] = 1;
  34. timer[pwm_number]->channel[channel].control = TIMER_CR_INTERRUPT_MASK | TIMER_CR_PWM_ENABLE | TIMER_CR_USER_MODE | TIMER_CR_ENABLE;
  35. } else
  36. {
  37. timer[pwm_number]->channel[channel].control = TIMER_CR_INTERRUPT_MASK;
  38. }
  39. }
  40. double pwm_set_frequency(pwm_device_number_t pwm_number, pwm_channel_number_t channel, double frequency, double duty)
  41. {
  42. uint32_t clk_freq = sysctl_clock_get_freq(SYSCTL_CLOCK_TIMER0 + pwm_number);
  43. int32_t periods = (int32_t)(clk_freq / frequency);
  44. configASSERT(periods > 0 && periods <= INT32_MAX);
  45. frequency = clk_freq / (double)periods;
  46. uint32_t percent = (uint32_t)(duty * periods);
  47. timer[pwm_number]->channel[channel].load_count = periods - percent;
  48. timer[pwm_number]->load_count2[channel] = percent;
  49. return frequency;
  50. }