pwm_current.c 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. /*
  2. * Xytronic LF-1600
  3. * Current PWM
  4. *
  5. * Copyright (c) 2015-2017 Michael Buesch <m@bues.ch>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, write to the Free Software Foundation, Inc.,
  19. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. */
  21. #include "pwm_current.h"
  22. #include "scale.h"
  23. #include "controller_current.h"
  24. #include "util.h"
  25. #include <avr/io.h>
  26. /* The max duty value (which actually is min current).
  27. * Note that changing this changes the PWM frequency.
  28. */
  29. #define PWMCURR_MAX_DUTY 0x1FFF
  30. void pwmcurr_set(fixpt_t current_amps)
  31. {
  32. uint16_t duty;
  33. /* Scale amps to duty cycle duration.
  34. * Scaling is inverse:
  35. * 0 -> full current
  36. * pwm-max -> no current
  37. */
  38. duty = (uint16_t)unscale(current_amps,
  39. float_to_fixpt(CONTRCURR_NEGLIM),
  40. float_to_fixpt(CONTRCURR_POSLIM),
  41. (int16_t)PWMCURR_MAX_DUTY, 0);
  42. /* Program the hardware */
  43. OCR1A = duty;
  44. }
  45. void pwmcurr_init(void)
  46. {
  47. build_assert(F_CPU == 8000000UL);
  48. /* Configure the port as output; high level. */
  49. PORTB |= (1 << PB1);
  50. DDRB |= (1 << DDB1);
  51. /* Set frequency and initial duty cycle. */
  52. ICR1 = (uint16_t)PWMCURR_MAX_DUTY;
  53. OCR1A = (uint16_t)PWMCURR_MAX_DUTY;
  54. /* Enable timer: Fast PWM (Mode 14), OC1A clr/set, PS 256 */
  55. TCCR1A = (1 << COM1A1) | (0 << COM1A0) |
  56. (0 << COM1B1) | (0 << COM1B0) |
  57. (1 << WGM11) | (0 << WGM10);
  58. TCCR1C = 0;
  59. TCCR1B = (1 << WGM13) | (1 << WGM12) |
  60. (1 << CS12) | (0 << CS11) | (0 << CS10);
  61. TCNT1 = 0;
  62. }