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.

fastio.h 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  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. #pragma once
  23. /**
  24. * Fast I/O Routines for AVR
  25. * Use direct port manipulation to save scads of processor time.
  26. * Contributed by Triffid_Hunter and modified by Kliment, thinkyhead, Bob-the-Kuhn, et.al.
  27. */
  28. #include <avr/io.h>
  29. #if defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1286P__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB646P__) || defined(__AVR_AT90USB647__)
  30. #define AVR_AT90USB1286_FAMILY 1
  31. #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__)
  32. #define AVR_ATmega1284_FAMILY 1
  33. #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  34. #define AVR_ATmega2560_FAMILY 1
  35. #elif defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
  36. #define AVR_ATmega2561_FAMILY 1
  37. #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
  38. #define AVR_ATmega328_FAMILY 1
  39. #endif
  40. /**
  41. * Include Ports and Functions
  42. */
  43. #if AVR_ATmega328_FAMILY
  44. #include "fastio/fastio_168.h"
  45. #elif AVR_ATmega1284_FAMILY
  46. #include "fastio/fastio_644.h"
  47. #elif AVR_ATmega2560_FAMILY
  48. #include "fastio/fastio_1280.h"
  49. #elif AVR_AT90USB1286_FAMILY
  50. #include "fastio/fastio_AT90USB.h"
  51. #elif AVR_ATmega2561_FAMILY
  52. #include "fastio/fastio_1281.h"
  53. #else
  54. #error "No FastIO definition for the selected AVR Board."
  55. #endif
  56. /**
  57. * Magic I/O routines
  58. *
  59. * Now you can simply SET_OUTPUT(PIN); WRITE(PIN, HIGH); WRITE(PIN, LOW);
  60. *
  61. * Why double up on these macros? see https://gcc.gnu.org/onlinedocs/cpp/Stringification.html
  62. */
  63. #define _READ(IO) TEST(DIO ## IO ## _RPORT, DIO ## IO ## _PIN)
  64. #define _WRITE_NC(IO,V) do{ \
  65. if (V) SBI(DIO ## IO ## _WPORT, DIO ## IO ## _PIN); \
  66. else CBI(DIO ## IO ## _WPORT, DIO ## IO ## _PIN); \
  67. }while(0)
  68. #define _WRITE_C(IO,V) do{ \
  69. uint8_t port_bits = DIO ## IO ## _WPORT; /* Get a mask from the current port bits */ \
  70. if (V) port_bits = ~port_bits; /* For setting bits, invert the mask */ \
  71. DIO ## IO ## _RPORT = port_bits & _BV(DIO ## IO ## _PIN); /* Atomically toggle the output port bits */ \
  72. }while(0)
  73. #define _WRITE(IO,V) do{ if (&(DIO ## IO ## _RPORT) < (uint8_t*)0x100) _WRITE_NC(IO,V); else _WRITE_C(IO,V); }while(0)
  74. #define _TOGGLE(IO) (DIO ## IO ## _RPORT = _BV(DIO ## IO ## _PIN))
  75. #define _SET_INPUT(IO) CBI(DIO ## IO ## _DDR, DIO ## IO ## _PIN)
  76. #define _SET_OUTPUT(IO) SBI(DIO ## IO ## _DDR, DIO ## IO ## _PIN)
  77. #define _IS_INPUT(IO) !TEST(DIO ## IO ## _DDR, DIO ## IO ## _PIN)
  78. #define _IS_OUTPUT(IO) TEST(DIO ## IO ## _DDR, DIO ## IO ## _PIN)
  79. // digitalRead/Write wrappers
  80. #ifdef FASTIO_EXT_START
  81. void extDigitalWrite(const int8_t pin, const uint8_t state);
  82. uint8_t extDigitalRead(const int8_t pin);
  83. #else
  84. #define extDigitalWrite(IO,V) digitalWrite(IO,V)
  85. #define extDigitalRead(IO) digitalRead(IO)
  86. #endif
  87. #define READ(IO) _READ(IO)
  88. #define WRITE(IO,V) _WRITE(IO,V)
  89. #define TOGGLE(IO) _TOGGLE(IO)
  90. #define SET_INPUT(IO) _SET_INPUT(IO)
  91. #define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _WRITE(IO, HIGH); }while(0)
  92. #define SET_INPUT_PULLDOWN SET_INPUT
  93. #define SET_OUTPUT(IO) _SET_OUTPUT(IO)
  94. #define SET_PWM SET_OUTPUT
  95. #define IS_INPUT(IO) _IS_INPUT(IO)
  96. #define IS_OUTPUT(IO) _IS_OUTPUT(IO)
  97. #define OUT_WRITE(IO,V) do{ SET_OUTPUT(IO); WRITE(IO,V); }while(0)
  98. /**
  99. * Timer and Interrupt Control
  100. */
  101. // Waveform Generation Modes
  102. enum WaveGenMode : char {
  103. WGM_NORMAL, // 0
  104. WGM_PWM_PC_8, // 1
  105. WGM_PWM_PC_9, // 2
  106. WGM_PWM_PC_10, // 3
  107. WGM_CTC_OCRnA, // 4 COM OCnx
  108. WGM_FAST_PWM_8, // 5
  109. WGM_FAST_PWM_9, // 6
  110. WGM_FAST_PWM_10, // 7
  111. WGM_PWM_PC_FC_ICRn, // 8
  112. WGM_PWM_PC_FC_OCRnA, // 9 COM OCnA
  113. WGM_PWM_PC_ICRn, // 10
  114. WGM_PWM_PC_OCRnA, // 11 COM OCnA
  115. WGM_CTC_ICRn, // 12 COM OCnx
  116. WGM_reserved, // 13
  117. WGM_FAST_PWM_ICRn, // 14 COM OCnA
  118. WGM_FAST_PWM_OCRnA // 15 COM OCnA
  119. };
  120. // Wavefore Generation Modes (Timer 2 only)
  121. enum WaveGenMode2 : char {
  122. WGM2_NORMAL, // 0
  123. WGM2_PWM_PC, // 1
  124. WGM2_CTC_OCR2A, // 2
  125. WGM2_FAST_PWM, // 3
  126. WGM2_reserved_1, // 4
  127. WGM2_PWM_PC_OCR2A, // 5
  128. WGM2_reserved_2, // 6
  129. WGM2_FAST_PWM_OCR2A, // 7
  130. };
  131. // Compare Modes
  132. enum CompareMode : char {
  133. COM_NORMAL, // 0
  134. COM_TOGGLE, // 1 Non-PWM: OCnx ... Both PWM (WGM 9,11,14,15): OCnA only ... else NORMAL
  135. COM_CLEAR_SET, // 2 Non-PWM: OCnx ... Fast PWM: OCnx/Bottom ... PF-FC: OCnx Up/Down
  136. COM_SET_CLEAR // 3 Non-PWM: OCnx ... Fast PWM: OCnx/Bottom ... PF-FC: OCnx Up/Down
  137. };
  138. // Clock Sources
  139. enum ClockSource : char {
  140. CS_NONE, // 0
  141. CS_PRESCALER_1, // 1
  142. CS_PRESCALER_8, // 2
  143. CS_PRESCALER_64, // 3
  144. CS_PRESCALER_256, // 4
  145. CS_PRESCALER_1024, // 5
  146. CS_EXT_FALLING, // 6
  147. CS_EXT_RISING // 7
  148. };
  149. // Clock Sources (Timer 2 only)
  150. enum ClockSource2 : char {
  151. CS2_NONE, // 0
  152. CS2_PRESCALER_1, // 1
  153. CS2_PRESCALER_8, // 2
  154. CS2_PRESCALER_32, // 3
  155. CS2_PRESCALER_64, // 4
  156. CS2_PRESCALER_128, // 5
  157. CS2_PRESCALER_256, // 6
  158. CS2_PRESCALER_1024 // 7
  159. };
  160. // Get interrupt bits in an orderly way
  161. // Ex: cs = GET_CS(0); coma1 = GET_COM(A,1);
  162. #define GET_WGM(T) (((TCCR##T##A >> WGM##T##0) & 0x3) | ((TCCR##T##B >> WGM##T##2 << 2) & 0xC))
  163. #define GET_CS(T) ((TCCR##T##B >> CS##T##0) & 0x7)
  164. #define GET_COM(T,Q) ((TCCR##T##Q >> COM##T##Q##0) & 0x3)
  165. #define GET_COMA(T) GET_COM(T,A)
  166. #define GET_COMB(T) GET_COM(T,B)
  167. #define GET_COMC(T) GET_COM(T,C)
  168. #define GET_ICNC(T) (!!(TCCR##T##B & _BV(ICNC##T)))
  169. #define GET_ICES(T) (!!(TCCR##T##B & _BV(ICES##T)))
  170. #define GET_FOC(T,Q) (!!(TCCR##T##C & _BV(FOC##T##Q)))
  171. #define GET_FOCA(T) GET_FOC(T,A)
  172. #define GET_FOCB(T) GET_FOC(T,B)
  173. #define GET_FOCC(T) GET_FOC(T,C)
  174. // Set Wave Generation Mode bits
  175. // Ex: SET_WGM(5,CTC_ICRn);
  176. #define _SET_WGM(T,V) do{ \
  177. TCCR##T##A = (TCCR##T##A & ~(0x3 << WGM##T##0)) | (( int(V) & 0x3) << WGM##T##0); \
  178. TCCR##T##B = (TCCR##T##B & ~(0x3 << WGM##T##2)) | (((int(V) >> 2) & 0x3) << WGM##T##2); \
  179. }while(0)
  180. #define SET_WGM(T,V) _SET_WGM(T,WGM_##V)
  181. // Runtime (see set_pwm_frequency):
  182. #define _SET_WGMnQ(TCCRnQ, V) do{ \
  183. *(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << 0)) | (( int(V) & 0x3) << 0); \
  184. *(TCCRnQ)[1] = (*(TCCRnQ)[1] & ~(0x3 << 3)) | (((int(V) >> 2) & 0x3) << 3); \
  185. }while(0)
  186. // Set Clock Select bits
  187. // Ex: SET_CS3(PRESCALER_64);
  188. #define _SET_CS(T,V) (TCCR##T##B = (TCCR##T##B & ~(0x7 << CS##T##0)) | ((int(V) & 0x7) << CS##T##0))
  189. #define _SET_CS0(V) _SET_CS(0,V)
  190. #define _SET_CS1(V) _SET_CS(1,V)
  191. #ifdef TCCR2
  192. #define _SET_CS2(V) (TCCR2 = (TCCR2 & ~(0x7 << CS20)) | (int(V) << CS20))
  193. #else
  194. #define _SET_CS2(V) _SET_CS(2,V)
  195. #endif
  196. #define _SET_CS3(V) _SET_CS(3,V)
  197. #define _SET_CS4(V) _SET_CS(4,V)
  198. #define _SET_CS5(V) _SET_CS(5,V)
  199. #define SET_CS0(V) _SET_CS0(CS_##V)
  200. #define SET_CS1(V) _SET_CS1(CS_##V)
  201. #ifdef TCCR2
  202. #define SET_CS2(V) _SET_CS2(CS2_##V)
  203. #else
  204. #define SET_CS2(V) _SET_CS2(CS_##V)
  205. #endif
  206. #define SET_CS3(V) _SET_CS3(CS_##V)
  207. #define SET_CS4(V) _SET_CS4(CS_##V)
  208. #define SET_CS5(V) _SET_CS5(CS_##V)
  209. #define SET_CS(T,V) SET_CS##T(V)
  210. // Runtime (see set_pwm_frequency)
  211. #define _SET_CSn(TCCRnQ, V) do{ \
  212. (*(TCCRnQ)[1] = (*(TCCRnQ[1]) & ~(0x7 << 0)) | ((int(V) & 0x7) << 0)); \
  213. }while(0)
  214. // Set Compare Mode bits
  215. // Ex: SET_COMS(4,CLEAR_SET,CLEAR_SET,CLEAR_SET);
  216. #define _SET_COM(T,Q,V) (TCCR##T##Q = (TCCR##T##Q & ~(0x3 << COM##T##Q##0)) | (int(V) << COM##T##Q##0))
  217. #define SET_COM(T,Q,V) _SET_COM(T,Q,COM_##V)
  218. #define SET_COMA(T,V) SET_COM(T,A,V)
  219. #define SET_COMB(T,V) SET_COM(T,B,V)
  220. #define SET_COMC(T,V) SET_COM(T,C,V)
  221. #define SET_COMS(T,V1,V2,V3) do{ SET_COMA(T,V1); SET_COMB(T,V2); SET_COMC(T,V3); }while(0)
  222. // Runtime (see set_pwm_duty)
  223. #define _SET_COMnQ(TCCRnQ, Q, V) do{ \
  224. (*(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << (6-2*(Q)))) | (int(V) << (6-2*(Q)))); \
  225. }while(0)
  226. // Set OCRnQ register
  227. // Runtime (see set_pwm_duty):
  228. #define _SET_OCRnQ(OCRnQ, Q, V) do{ \
  229. (*(OCRnQ)[(Q)] = (0x0000) | (int(V) & 0xFFFF)); \
  230. }while(0)
  231. // Set ICRn register (one per timer)
  232. // Runtime (see set_pwm_frequency)
  233. #define _SET_ICRn(ICRn, V) do{ \
  234. (*(ICRn) = (0x0000) | (int(V) & 0xFFFF)); \
  235. }while(0)
  236. // Set Noise Canceler bit
  237. // Ex: SET_ICNC(2,1)
  238. #define SET_ICNC(T,V) (TCCR##T##B = (V) ? TCCR##T##B | _BV(ICNC##T) : TCCR##T##B & ~_BV(ICNC##T))
  239. // Set Input Capture Edge Select bit
  240. // Ex: SET_ICES(5,0)
  241. #define SET_ICES(T,V) (TCCR##T##B = (V) ? TCCR##T##B | _BV(ICES##T) : TCCR##T##B & ~_BV(ICES##T))
  242. // Set Force Output Compare bit
  243. // Ex: SET_FOC(3,A,1)
  244. #define SET_FOC(T,Q,V) (TCCR##T##C = (V) ? TCCR##T##C | _BV(FOC##T##Q) : TCCR##T##C & ~_BV(FOC##T##Q))
  245. #define SET_FOCA(T,V) SET_FOC(T,A,V)
  246. #define SET_FOCB(T,V) SET_FOC(T,B,V)
  247. #define SET_FOCC(T,V) SET_FOC(T,C,V)
  248. #if 0
  249. /**
  250. * PWM availability macros
  251. */
  252. // Determine which harware PWMs are already in use
  253. #define _PWM_CHK_FAN_B(P) (P == E0_AUTO_FAN_PIN || P == E1_AUTO_FAN_PIN || P == E2_AUTO_FAN_PIN || P == E3_AUTO_FAN_PIN || P == E4_AUTO_FAN_PIN || P == E5_AUTO_FAN_PIN || P == E6_AUTO_FAN_PIN || P == E7_AUTO_FAN_PIN || P == CHAMBER_AUTO_FAN_PIN)
  254. #if PIN_EXISTS(CONTROLLER_FAN)
  255. #define PWM_CHK_FAN_B(P) (_PWM_CHK_FAN_B(P) || P == CONTROLLER_FAN_PIN)
  256. #else
  257. #define PWM_CHK_FAN_B(P) _PWM_CHK_FAN_B(P)
  258. #endif
  259. #if ANY_PIN(FAN, FAN1, FAN2, FAN3, FAN4, FAN5, FAN6, FAN7)
  260. #if PIN_EXISTS(FAN7)
  261. #define PWM_CHK_FAN_A(P) (P == FAN0_PIN || P == FAN1_PIN || P == FAN2_PIN || P == FAN3_PIN || P == FAN4_PIN || P == FAN5_PIN || P == FAN6_PIN || P == FAN7_PIN)
  262. #elif PIN_EXISTS(FAN6)
  263. #define PWM_CHK_FAN_A(P) (P == FAN0_PIN || P == FAN1_PIN || P == FAN2_PIN || P == FAN3_PIN || P == FAN4_PIN || P == FAN5_PIN || P == FAN6_PIN)
  264. #elif PIN_EXISTS(FAN5)
  265. #define PWM_CHK_FAN_A(P) (P == FAN0_PIN || P == FAN1_PIN || P == FAN2_PIN || P == FAN3_PIN || P == FAN4_PIN || P == FAN5_PIN)
  266. #elif PIN_EXISTS(FAN4)
  267. #define PWM_CHK_FAN_A(P) (P == FAN0_PIN || P == FAN1_PIN || P == FAN2_PIN || P == FAN3_PIN || P == FAN4_PIN)
  268. #elif PIN_EXISTS(FAN3)
  269. #define PWM_CHK_FAN_A(P) (P == FAN0_PIN || P == FAN1_PIN || P == FAN2_PIN || P == FAN3_PIN)
  270. #elif PIN_EXISTS(FAN2)
  271. #define PWM_CHK_FAN_A(P) (P == FAN0_PIN || P == FAN1_PIN || P == FAN2_PIN)
  272. #elif PIN_EXISTS(FAN1)
  273. #define PWM_CHK_FAN_A(P) (P == FAN0_PIN || P == FAN1_PIN)
  274. #else
  275. #define PWM_CHK_FAN_A(P) (P == FAN0_PIN)
  276. #endif
  277. #else
  278. #define PWM_CHK_FAN_A(P) false
  279. #endif
  280. #if HAS_MOTOR_CURRENT_PWM
  281. #if PIN_EXISTS(MOTOR_CURRENT_PWM_XY)
  282. #define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E || P == MOTOR_CURRENT_PWM_Z || P == MOTOR_CURRENT_PWM_XY)
  283. #elif PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
  284. #define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E || P == MOTOR_CURRENT_PWM_Z)
  285. #else
  286. #define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E)
  287. #endif
  288. #else
  289. #define PWM_CHK_MOTOR_CURRENT(P) false
  290. #endif
  291. #ifdef NUM_SERVOS
  292. #if AVR_ATmega2560_FAMILY
  293. #define PWM_CHK_SERVO(P) (P == 5 || (NUM_SERVOS > 12 && P == 6) || (NUM_SERVOS > 24 && P == 46)) // PWMS 3A, 4A & 5A
  294. #elif AVR_ATmega2561_FAMILY
  295. #define PWM_CHK_SERVO(P) (P == 5) // PWM3A
  296. #elif AVR_ATmega1284_FAMILY
  297. #define PWM_CHK_SERVO(P) false
  298. #elif AVR_AT90USB1286_FAMILY
  299. #define PWM_CHK_SERVO(P) (P == 16) // PWM3A
  300. #elif AVR_ATmega328_FAMILY
  301. #define PWM_CHK_SERVO(P) false
  302. #endif
  303. #else
  304. #define PWM_CHK_SERVO(P) false
  305. #endif
  306. #if ENABLED(BARICUDA)
  307. #if HAS_HEATER_1 && HAS_HEATER_2
  308. #define PWM_CHK_HEATER(P) (P == HEATER_1_PIN || P == HEATER_2_PIN)
  309. #elif HAS_HEATER_1
  310. #define PWM_CHK_HEATER(P) (P == HEATER_1_PIN)
  311. #endif
  312. #else
  313. #define PWM_CHK_HEATER(P) false
  314. #endif
  315. #define PWM_CHK(P) (PWM_CHK_HEATER(P) || PWM_CHK_SERVO(P) || PWM_CHK_MOTOR_CURRENT(P) || PWM_CHK_FAN_A(P) || PWM_CHK_FAN_B(P))
  316. #endif // PWM_CHK is not used in Marlin
  317. // define which hardware PWMs are available for the current CPU
  318. // all timer 1 PWMS deleted from this list because they are never available
  319. #if AVR_ATmega2560_FAMILY
  320. #define PWM_PIN(P) ((P >= 2 && P <= 10) || P == 13 || P == 44 || P == 45 || P == 46)
  321. #elif AVR_ATmega2561_FAMILY
  322. #define PWM_PIN(P) ((P >= 2 && P <= 6) || P == 9)
  323. #elif AVR_ATmega1284_FAMILY
  324. #define PWM_PIN(P) (P == 3 || P == 4 || P == 14 || P == 15)
  325. #elif AVR_AT90USB1286_FAMILY
  326. #define PWM_PIN(P) (P == 0 || P == 1 || P == 14 || P == 15 || P == 16 || P == 24)
  327. #elif AVR_ATmega328_FAMILY
  328. #define PWM_PIN(P) (P == 3 || P == 5 || P == 6 || P == 11)
  329. #else
  330. #error "unknown CPU"
  331. #endif