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 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. * servo.cpp - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
  24. * Copyright (c) 2009 Michael Margolis. All right reserved.
  25. */
  26. /**
  27. * A servo is activated by creating an instance of the Servo class passing the desired pin to the attach() method.
  28. * The servos are pulsed in the background using the value most recently written using the write() method
  29. *
  30. * Note that analogWrite of PWM on pins associated with the timer are disabled when the first servo is attached.
  31. * Timers are seized as needed in groups of 12 servos - 24 servos use two timers, 48 servos will use four.
  32. *
  33. * The methods are:
  34. *
  35. * Servo - Class for manipulating servo motors connected to Arduino pins.
  36. *
  37. * attach(pin) - Attach a servo motor to an i/o pin.
  38. * attach(pin, min, max) - Attach to a pin, setting min and max values in microseconds
  39. * Default min is 544, max is 2400
  40. *
  41. * write() - Set the servo angle in degrees. (Invalid angles —over MIN_PULSE_WIDTH— are treated as µs.)
  42. * writeMicroseconds() - Set the servo pulse width in microseconds.
  43. * move(pin, angle) - Sequence of attach(pin), write(angle), safe_delay(servo_delay[servoIndex]).
  44. * With DEACTIVATE_SERVOS_AFTER_MOVE it detaches after servo_delay[servoIndex].
  45. * read() - Get the last-written servo pulse width as an angle between 0 and 180.
  46. * readMicroseconds() - Get the last-written servo pulse width in microseconds.
  47. * attached() - Return true if a servo is attached.
  48. * detach() - Stop an attached servo from pulsing its i/o pin.
  49. */
  50. #ifdef __AVR__
  51. #include "../../inc/MarlinConfig.h"
  52. #if HAS_SERVOS
  53. #include <avr/interrupt.h>
  54. #include "../shared/servo.h"
  55. #include "../shared/servo_private.h"
  56. static volatile int8_t Channel[_Nbr_16timers]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
  57. /************ static functions common to all instances ***********************/
  58. static inline void handle_interrupts(const timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
  59. int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
  60. if (cho < 0) // Channel -1 indicates the refresh interval completed...
  61. *TCNTn = 0; // ...so reset the timer
  62. else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
  63. extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
  64. Channel[timer] = ++cho; // Handle the next channel (or 0)
  65. if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
  66. *OCRnA = *TCNTn + SERVO(timer, cho).ticks; // set compare to current ticks plus duration
  67. if (SERVO(timer, cho).Pin.isActive) // activated?
  68. extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
  69. }
  70. else {
  71. // finished all channels so wait for the refresh period to expire before starting over
  72. const unsigned int cval = ((unsigned)*TCNTn) + 32 / (SERVO_TIMER_PRESCALER), // allow 32 cycles to ensure the next OCR1A not missed
  73. ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
  74. *OCRnA = max(cval, ival);
  75. Channel[timer] = -1; // reset the timer counter to 0 on the next call
  76. }
  77. }
  78. #ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform
  79. // Interrupt handlers for Arduino
  80. #ifdef _useTimer1
  81. SIGNAL(TIMER1_COMPA_vect) { handle_interrupts(_timer1, &TCNT1, &OCR1A); }
  82. #endif
  83. #ifdef _useTimer3
  84. SIGNAL(TIMER3_COMPA_vect) { handle_interrupts(_timer3, &TCNT3, &OCR3A); }
  85. #endif
  86. #ifdef _useTimer4
  87. SIGNAL(TIMER4_COMPA_vect) { handle_interrupts(_timer4, &TCNT4, &OCR4A); }
  88. #endif
  89. #ifdef _useTimer5
  90. SIGNAL(TIMER5_COMPA_vect) { handle_interrupts(_timer5, &TCNT5, &OCR5A); }
  91. #endif
  92. #else // WIRING
  93. // Interrupt handlers for Wiring
  94. #ifdef _useTimer1
  95. void Timer1Service() { handle_interrupts(_timer1, &TCNT1, &OCR1A); }
  96. #endif
  97. #ifdef _useTimer3
  98. void Timer3Service() { handle_interrupts(_timer3, &TCNT3, &OCR3A); }
  99. #endif
  100. #endif // WIRING
  101. /****************** end of static functions ******************************/
  102. void initISR(const timer16_Sequence_t timer_index) {
  103. switch (timer_index) {
  104. default: break;
  105. #ifdef _useTimer1
  106. case _timer1:
  107. TCCR1A = 0; // normal counting mode
  108. TCCR1B = _BV(CS11); // set prescaler of 8
  109. TCNT1 = 0; // clear the timer count
  110. #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
  111. SBI(TIFR, OCF1A); // clear any pending interrupts;
  112. SBI(TIMSK, OCIE1A); // enable the output compare interrupt
  113. #else
  114. // here if not ATmega8 or ATmega128
  115. SBI(TIFR1, OCF1A); // clear any pending interrupts;
  116. SBI(TIMSK1, OCIE1A); // enable the output compare interrupt
  117. #endif
  118. #ifdef WIRING
  119. timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
  120. #endif
  121. break;
  122. #endif
  123. #ifdef _useTimer3
  124. case _timer3:
  125. TCCR3A = 0; // normal counting mode
  126. TCCR3B = _BV(CS31); // set prescaler of 8
  127. TCNT3 = 0; // clear the timer count
  128. #ifdef __AVR_ATmega128__
  129. SBI(TIFR, OCF3A); // clear any pending interrupts;
  130. SBI(ETIMSK, OCIE3A); // enable the output compare interrupt
  131. #else
  132. SBI(TIFR3, OCF3A); // clear any pending interrupts;
  133. SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
  134. #endif
  135. #ifdef WIRING
  136. timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
  137. #endif
  138. break;
  139. #endif
  140. #ifdef _useTimer4
  141. case _timer4:
  142. TCCR4A = 0; // normal counting mode
  143. TCCR4B = _BV(CS41); // set prescaler of 8
  144. TCNT4 = 0; // clear the timer count
  145. TIFR4 = _BV(OCF4A); // clear any pending interrupts;
  146. TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
  147. break;
  148. #endif
  149. #ifdef _useTimer5
  150. case _timer5:
  151. TCCR5A = 0; // normal counting mode
  152. TCCR5B = _BV(CS51); // set prescaler of 8
  153. TCNT5 = 0; // clear the timer count
  154. TIFR5 = _BV(OCF5A); // clear any pending interrupts;
  155. TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
  156. break;
  157. #endif
  158. }
  159. }
  160. void finISR(const timer16_Sequence_t timer_index) {
  161. // Disable use of the given timer
  162. #ifdef WIRING
  163. switch (timer_index) {
  164. default: break;
  165. case _timer1:
  166. CBI(
  167. #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
  168. TIMSK1
  169. #else
  170. TIMSK
  171. #endif
  172. , OCIE1A // disable timer 1 output compare interrupt
  173. );
  174. timerDetach(TIMER1OUTCOMPAREA_INT);
  175. break;
  176. case _timer3:
  177. CBI(
  178. #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
  179. TIMSK3
  180. #else
  181. ETIMSK
  182. #endif
  183. , OCIE3A // disable the timer3 output compare A interrupt
  184. );
  185. timerDetach(TIMER3OUTCOMPAREA_INT);
  186. break;
  187. }
  188. #else // !WIRING
  189. // For arduino - in future: call here to a currently undefined function to reset the timer
  190. UNUSED(timer_index);
  191. #endif
  192. }
  193. #endif // HAS_SERVOS
  194. #endif // __AVR__