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.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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. */
  51. #ifdef __AVR__
  52. #include "../../inc/MarlinConfig.h"
  53. #if HAS_SERVOS
  54. #include <avr/interrupt.h>
  55. #include "../shared/servo.h"
  56. #include "../shared/servo_private.h"
  57. static volatile int8_t Channel[_Nbr_16timers]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
  58. /************ static functions common to all instances ***********************/
  59. static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
  60. if (Channel[timer] < 0)
  61. *TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
  62. else {
  63. if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
  64. extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
  65. }
  66. Channel[timer]++; // increment to the next channel
  67. if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
  68. *OCRnA = *TCNTn + SERVO(timer, Channel[timer]).ticks;
  69. if (SERVO(timer, Channel[timer]).Pin.isActive) // check if activated
  70. extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // it's an active channel so pulse it high
  71. }
  72. else {
  73. // finished all channels so wait for the refresh period to expire before starting over
  74. if (((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL)) // allow a few ticks to ensure the next OCR1A not missed
  75. *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
  76. else
  77. *OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
  78. Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
  79. }
  80. }
  81. #ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform
  82. // Interrupt handlers for Arduino
  83. #ifdef _useTimer1
  84. SIGNAL(TIMER1_COMPA_vect) { handle_interrupts(_timer1, &TCNT1, &OCR1A); }
  85. #endif
  86. #ifdef _useTimer3
  87. SIGNAL(TIMER3_COMPA_vect) { handle_interrupts(_timer3, &TCNT3, &OCR3A); }
  88. #endif
  89. #ifdef _useTimer4
  90. SIGNAL(TIMER4_COMPA_vect) { handle_interrupts(_timer4, &TCNT4, &OCR4A); }
  91. #endif
  92. #ifdef _useTimer5
  93. SIGNAL(TIMER5_COMPA_vect) { handle_interrupts(_timer5, &TCNT5, &OCR5A); }
  94. #endif
  95. #else // WIRING
  96. // Interrupt handlers for Wiring
  97. #ifdef _useTimer1
  98. void Timer1Service() { handle_interrupts(_timer1, &TCNT1, &OCR1A); }
  99. #endif
  100. #ifdef _useTimer3
  101. void Timer3Service() { handle_interrupts(_timer3, &TCNT3, &OCR3A); }
  102. #endif
  103. #endif // WIRING
  104. /****************** end of static functions ******************************/
  105. void initISR(timer16_Sequence_t timer) {
  106. #ifdef _useTimer1
  107. if (timer == _timer1) {
  108. TCCR1A = 0; // normal counting mode
  109. TCCR1B = _BV(CS11); // set prescaler of 8
  110. TCNT1 = 0; // clear the timer count
  111. #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
  112. SBI(TIFR, OCF1A); // clear any pending interrupts;
  113. SBI(TIMSK, OCIE1A); // enable the output compare interrupt
  114. #else
  115. // here if not ATmega8 or ATmega128
  116. SBI(TIFR1, OCF1A); // clear any pending interrupts;
  117. SBI(TIMSK1, OCIE1A); // enable the output compare interrupt
  118. #endif
  119. #ifdef WIRING
  120. timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
  121. #endif
  122. }
  123. #endif
  124. #ifdef _useTimer3
  125. if (timer == _timer3) {
  126. TCCR3A = 0; // normal counting mode
  127. TCCR3B = _BV(CS31); // set prescaler of 8
  128. TCNT3 = 0; // clear the timer count
  129. #ifdef __AVR_ATmega128__
  130. SBI(TIFR, OCF3A); // clear any pending interrupts;
  131. SBI(ETIMSK, OCIE3A); // enable the output compare interrupt
  132. #else
  133. SBI(TIFR3, OCF3A); // clear any pending interrupts;
  134. SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
  135. #endif
  136. #ifdef WIRING
  137. timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
  138. #endif
  139. }
  140. #endif
  141. #ifdef _useTimer4
  142. if (timer == _timer4) {
  143. TCCR4A = 0; // normal counting mode
  144. TCCR4B = _BV(CS41); // set prescaler of 8
  145. TCNT4 = 0; // clear the timer count
  146. TIFR4 = _BV(OCF4A); // clear any pending interrupts;
  147. TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
  148. }
  149. #endif
  150. #ifdef _useTimer5
  151. if (timer == _timer5) {
  152. TCCR5A = 0; // normal counting mode
  153. TCCR5B = _BV(CS51); // set prescaler of 8
  154. TCNT5 = 0; // clear the timer count
  155. TIFR5 = _BV(OCF5A); // clear any pending interrupts;
  156. TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
  157. }
  158. #endif
  159. }
  160. void finISR(timer16_Sequence_t timer) {
  161. // Disable use of the given timer
  162. #ifdef WIRING
  163. if (timer == _timer1) {
  164. CBI(
  165. #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
  166. TIMSK1
  167. #else
  168. TIMSK
  169. #endif
  170. , OCIE1A); // disable timer 1 output compare interrupt
  171. timerDetach(TIMER1OUTCOMPAREA_INT);
  172. }
  173. else if (timer == _timer3) {
  174. CBI(
  175. #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
  176. TIMSK3
  177. #else
  178. ETIMSK
  179. #endif
  180. , OCIE3A); // disable the timer3 output compare A interrupt
  181. timerDetach(TIMER3OUTCOMPAREA_INT);
  182. }
  183. #else // !WIRING
  184. // For arduino - in future: call here to a currently undefined function to reset the timer
  185. UNUSED(timer);
  186. #endif
  187. }
  188. #endif // HAS_SERVOS
  189. #endif // __AVR__