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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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(timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
  59. if (Channel[timer] < 0)
  60. *TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
  61. else {
  62. if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
  63. extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
  64. }
  65. Channel[timer]++; // increment to the next channel
  66. if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
  67. *OCRnA = *TCNTn + SERVO(timer, Channel[timer]).ticks;
  68. if (SERVO(timer, Channel[timer]).Pin.isActive) // check if activated
  69. extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // it's an active channel so pulse it high
  70. }
  71. else {
  72. // finished all channels so wait for the refresh period to expire before starting over
  73. if (((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL)) // allow a few ticks to ensure the next OCR1A not missed
  74. *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
  75. else
  76. *OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
  77. Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
  78. }
  79. }
  80. #ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform
  81. // Interrupt handlers for Arduino
  82. #ifdef _useTimer1
  83. SIGNAL(TIMER1_COMPA_vect) { handle_interrupts(_timer1, &TCNT1, &OCR1A); }
  84. #endif
  85. #ifdef _useTimer3
  86. SIGNAL(TIMER3_COMPA_vect) { handle_interrupts(_timer3, &TCNT3, &OCR3A); }
  87. #endif
  88. #ifdef _useTimer4
  89. SIGNAL(TIMER4_COMPA_vect) { handle_interrupts(_timer4, &TCNT4, &OCR4A); }
  90. #endif
  91. #ifdef _useTimer5
  92. SIGNAL(TIMER5_COMPA_vect) { handle_interrupts(_timer5, &TCNT5, &OCR5A); }
  93. #endif
  94. #else // WIRING
  95. // Interrupt handlers for Wiring
  96. #ifdef _useTimer1
  97. void Timer1Service() { handle_interrupts(_timer1, &TCNT1, &OCR1A); }
  98. #endif
  99. #ifdef _useTimer3
  100. void Timer3Service() { handle_interrupts(_timer3, &TCNT3, &OCR3A); }
  101. #endif
  102. #endif // WIRING
  103. /****************** end of static functions ******************************/
  104. void initISR(timer16_Sequence_t timer) {
  105. #ifdef _useTimer1
  106. if (timer == _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. }
  122. #endif
  123. #ifdef _useTimer3
  124. if (timer == _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. }
  139. #endif
  140. #ifdef _useTimer4
  141. if (timer == _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. }
  148. #endif
  149. #ifdef _useTimer5
  150. if (timer == _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. }
  157. #endif
  158. }
  159. void finISR(timer16_Sequence_t timer) {
  160. // Disable use of the given timer
  161. #ifdef WIRING
  162. if (timer == _timer1) {
  163. CBI(
  164. #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
  165. TIMSK1
  166. #else
  167. TIMSK
  168. #endif
  169. , OCIE1A); // disable timer 1 output compare interrupt
  170. timerDetach(TIMER1OUTCOMPAREA_INT);
  171. }
  172. else if (timer == _timer3) {
  173. CBI(
  174. #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
  175. TIMSK3
  176. #else
  177. ETIMSK
  178. #endif
  179. , OCIE3A); // disable the timer3 output compare A interrupt
  180. timerDetach(TIMER3OUTCOMPAREA_INT);
  181. }
  182. #else // !WIRING
  183. // For arduino - in future: call here to a currently undefined function to reset the timer
  184. UNUSED(timer);
  185. #endif
  186. }
  187. #endif // HAS_SERVOS
  188. #endif // __AVR__