My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Servo.cpp 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. *
  21. */
  22. /*
  23. Copyright (c) 2013 Arduino LLC. All right reserved.
  24. This library is free software; you can redistribute it and/or
  25. modify it under the terms of the GNU Lesser General Public
  26. License as published by the Free Software Foundation; either
  27. version 2.1 of the License, or (at your option) any later version.
  28. This library is distributed in the hope that it will be useful,
  29. but WITHOUT ANY WARRANTY; without even the implied warranty of
  30. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  31. Lesser General Public License for more details.
  32. You should have received a copy of the GNU Lesser General Public
  33. License along with this library; if not, write to the Free Software
  34. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  35. */
  36. #ifdef ARDUINO_ARCH_SAM
  37. #include "../../inc/MarlinConfig.h"
  38. #if HAS_SERVOS
  39. #include "../shared/servo.h"
  40. #include "../shared/servo_private.h"
  41. static Flags<_Nbr_16timers> DisablePending; // ISR should disable the timer at the next timer reset
  42. // ------------------------
  43. /// Interrupt handler for the TC0 channel 1.
  44. // ------------------------
  45. void Servo_Handler(const timer16_Sequence_t, Tc*, const uint8_t);
  46. #ifdef _useTimer1
  47. void HANDLER_FOR_TIMER1() { Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1); }
  48. #endif
  49. #ifdef _useTimer2
  50. void HANDLER_FOR_TIMER2() { Servo_Handler(_timer2, TC_FOR_TIMER2, CHANNEL_FOR_TIMER2); }
  51. #endif
  52. #ifdef _useTimer3
  53. void HANDLER_FOR_TIMER3() { Servo_Handler(_timer3, TC_FOR_TIMER3, CHANNEL_FOR_TIMER3); }
  54. #endif
  55. #ifdef _useTimer4
  56. void HANDLER_FOR_TIMER4() { Servo_Handler(_timer4, TC_FOR_TIMER4, CHANNEL_FOR_TIMER4); }
  57. #endif
  58. #ifdef _useTimer5
  59. void HANDLER_FOR_TIMER5() { Servo_Handler(_timer5, TC_FOR_TIMER5, CHANNEL_FOR_TIMER5); }
  60. #endif
  61. void Servo_Handler(const timer16_Sequence_t timer, Tc *tc, const uint8_t channel) {
  62. static int8_t Channel[_Nbr_16timers]; // Servo counters to pulse (or -1 for refresh interval)
  63. int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
  64. if (cho < 0) { // Channel -1 indicates the refresh interval completed...
  65. tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // ...so reset the timer
  66. if (DisablePending[timer]) {
  67. // Disabling only after the full servo period expires prevents
  68. // pulses being too close together if immediately re-enabled.
  69. DisablePending.clear(timer);
  70. TC_Stop(tc, channel);
  71. tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
  72. return;
  73. }
  74. }
  75. else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
  76. extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
  77. Channel[timer] = ++cho; // go to the next channel (or 0)
  78. if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
  79. tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer, cho).ticks;
  80. if (SERVO(timer, cho).Pin.isActive) // activated?
  81. extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
  82. }
  83. else {
  84. // finished all channels so wait for the refresh period to expire before starting over
  85. const unsigned int cval = tc->TC_CHANNEL[channel].TC_CV + 128 / (SERVO_TIMER_PRESCALER), // allow 128 cycles to ensure the next CV not missed
  86. ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
  87. tc->TC_CHANNEL[channel].TC_RA = max(cval, ival);
  88. Channel[timer] = -1; // reset the timer CCR on the next call
  89. }
  90. tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
  91. }
  92. static void _initISR(Tc *tc, uint32_t channel, uint32_t id, IRQn_Type irqn) {
  93. pmc_enable_periph_clk(id);
  94. TC_Configure(tc, channel,
  95. TC_CMR_WAVE // Waveform mode
  96. | TC_CMR_WAVSEL_UP_RC // Counter running up and reset when equal to RC
  97. | (SERVO_TIMER_PRESCALER == 2 ? TC_CMR_TCCLKS_TIMER_CLOCK1 : 0) // MCK/2
  98. | (SERVO_TIMER_PRESCALER == 8 ? TC_CMR_TCCLKS_TIMER_CLOCK2 : 0) // MCK/8
  99. | (SERVO_TIMER_PRESCALER == 32 ? TC_CMR_TCCLKS_TIMER_CLOCK3 : 0) // MCK/32
  100. | (SERVO_TIMER_PRESCALER == 128 ? TC_CMR_TCCLKS_TIMER_CLOCK4 : 0) // MCK/128
  101. );
  102. // Wait 1ms before the first ISR
  103. TC_SetRA(tc, channel, (F_CPU) / (SERVO_TIMER_PRESCALER) / 1000UL); // 1ms
  104. // Configure and enable interrupt
  105. NVIC_EnableIRQ(irqn);
  106. tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS; // TC_IER_CPAS: RA Compare
  107. // Enables the timer clock and performs a software reset to start the counting
  108. TC_Start(tc, channel);
  109. }
  110. void initISR(const timer16_Sequence_t timer_index) {
  111. CRITICAL_SECTION_START();
  112. const bool disable_soon = DisablePending[timer_index];
  113. DisablePending.clear(timer_index);
  114. CRITICAL_SECTION_END();
  115. if (!disable_soon) switch (timer_index) {
  116. default: break;
  117. #ifdef _useTimer1
  118. case _timer1: return _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
  119. #endif
  120. #ifdef _useTimer2
  121. case _timer2: return _initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
  122. #endif
  123. #ifdef _useTimer3
  124. case _timer3: return _initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
  125. #endif
  126. #ifdef _useTimer4
  127. case _timer4: return _initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
  128. #endif
  129. #ifdef _useTimer5
  130. case _timer5: return _initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
  131. #endif
  132. }
  133. }
  134. void finISR(const timer16_Sequence_t timer_index) {
  135. // Timer is disabled from the ISR, to ensure proper final pulse length.
  136. DisablePending.set(timer_index);
  137. }
  138. #endif // HAS_SERVOS
  139. #endif // ARDUINO_ARCH_SAM