PageRenderTime 59ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/src/pins_teensy.c

https://bitbucket.org/makible/makibox-firmware
C | 455 lines | 352 code | 47 blank | 56 comment | 44 complexity | ee9e35e98a849f35ab8d86dcf2ea5e48 MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. Makibox A6 Firmware
  3. Based on Sprinter (master branch, 1 Sep 2012).
  4. Designed for Printrboard (Rev B).
  5. ---
  6. Copyright (c) 2012-2013 by Makible Limited.
  7. This file is part of the Makibox A6 Firmware.
  8. Makibox A6 Firmware 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. The Makibox A6 Firmware is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with the Makibox A6 Firmware. If not, see <http://www.gnu.org/licenses/>.
  18. ---
  19. * Pin functions for the Teensy and Teensy++
  20. * http://www.pjrc.com/teensy/
  21. * Copyright (c) 2008-2010 PJRC.COM, LLC
  22. *
  23. * Permission is hereby granted, free of charge, to any person obtaining a copy
  24. * of this software and associated documentation files (the "Software"), to deal
  25. * in the Software without restriction, including without limitation the rights
  26. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  27. * copies of the Software, and to permit persons to whom the Software is
  28. * furnished to do so, subject to the following conditions:
  29. *
  30. * The above copyright notice and this permission notice shall be included in
  31. * all copies or substantial portions of the Software.
  32. *
  33. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  34. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  35. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  36. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  37. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  38. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  39. * THE SOFTWARE.
  40. */
  41. #include <avr/io.h>
  42. #include <avr/interrupt.h>
  43. #include <avr/sleep.h>
  44. #include <stdio.h>
  45. #include <stdarg.h>
  46. #include <stdlib.h>
  47. #include "pgmspace.h"
  48. #include "pins_teensy.h"
  49. #ifdef ID
  50. #undef ID // ID bit in USBSTA conflicts with user's code
  51. #endif
  52. const static uint8_t A0 = CORE_ANALOG0_PIN;
  53. const static uint8_t A1 = CORE_ANALOG1_PIN;
  54. const static uint8_t A2 = CORE_ANALOG2_PIN;
  55. const static uint8_t A3 = CORE_ANALOG3_PIN;
  56. const static uint8_t A4 = CORE_ANALOG4_PIN;
  57. const static uint8_t A5 = CORE_ANALOG5_PIN;
  58. const static uint8_t A6 = CORE_ANALOG6_PIN;
  59. const static uint8_t A7 = CORE_ANALOG7_PIN;
  60. const static uint8_t SS = CORE_SS0_PIN;
  61. const static uint8_t MOSI = CORE_MOSI0_PIN;
  62. const static uint8_t MISO = CORE_MISO0_PIN;
  63. const static uint8_t SCK = CORE_SCLK0_PIN;
  64. const static uint8_t LED_BUILTIN = CORE_LED0_PIN;
  65. #if defined(CORE_SDA0_PIN)
  66. const static uint8_t SDA = CORE_SDA0_PIN;
  67. #endif
  68. #if defined(CORE_SCL0_PIN)
  69. const static uint8_t SCL = CORE_SCL0_PIN;
  70. #endif
  71. #define NUM_DIGITAL_PINS CORE_NUM_TOTAL_PINS
  72. #define NUM_ANALOG_INPUTS CORE_NUM_ANALOG
  73. #define digitalPinToPort(P) (P)
  74. #define portInputRegister(P) ((volatile uint8_t *)((int)pgm_read_byte(digital_pin_table_PGM+(P)*2+1)))
  75. #define portModeRegister(P) (portInputRegister(P) + 1)
  76. #define portOutputRegister(P) (portInputRegister(P) + 2)
  77. #define digitalPinToBitMask(P) (pgm_read_byte(digital_pin_table_PGM+(P)*2))
  78. extern const uint8_t digital_pin_table_PGM[] PROGMEM;
  79. #define analogInputToDigitalPin(ch) ((ch) <= 7 ? (ch) - 38 : -1)
  80. #define digitalPinHasPWM(p) (((p) >= 14 && (p) <= 16) || ((p) >= 24 && (p) <= 27) || (p) == 0 || (p) == 1)
  81. #define digitalPinToPortReg(p) \
  82. (((p) >= 0 && (p) <= 7) ? &PORTD : (((p) >= 10 && (p) <= 17) ? &PORTC : \
  83. (((p) >= 20 && (p) <= 27) ? &PORTB : (((p) >= 28 && (p) <= 35) ? &PORTA : \
  84. (((p) >= 38 && (p) <= 45) ? &PORTF : &PORTE)))))
  85. #define digitalPinToBit(p) \
  86. (((p) <= 7) ? (p) : (((p) <= 9) ? (p) - 8 : (((p) <= 17) ? (p) - 10 : \
  87. (((p) <= 19) ? (p) - 12 : (((p) <= 27) ? (p) - 20 : (((p) <= 35) ? (p) - 28 : \
  88. (((p) <= 37) ? (p) - 32 : (((p) <= 45) ? (p) - 38 : 2))))))))
  89. #define digitalPinToPCICR(p) (((p) >= 20 && (p) <= 27) ? &PCICR : NULL)
  90. #define digitalPinToPCICRbit(p) (0)
  91. #define digitalPinToPCIFR(p) (((p) >= 20 && (p) <= 27) ? &PCIFR : NULL)
  92. #define digitalPinToPCIFRbit(p) (0)
  93. #define digitalPinToPCMSK(p) (((p) >= 20 && (p) <= 27) ? &PCMSK0 : NULL)
  94. #define digitalPinToPCMSKbit(p) (((p) - 20) & 7)
  95. #ifndef cbi
  96. #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
  97. #endif
  98. #ifndef sbi
  99. #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
  100. #endif
  101. uint8_t w_analog_reference = 0x40;
  102. int analogRead(uint8_t pin)
  103. {
  104. uint8_t low, high;
  105. if (pin >= PIN_F0 && pin <= PIN_F7) pin -= PIN_F0;
  106. if (pin < 8) {
  107. DIDR0 |= (1 << pin);
  108. //DDRF &= ~(1 << pin);
  109. //PORTF &= ~(1 << pin);
  110. }
  111. ADMUX = w_analog_reference | (pin & 0x1F);
  112. ADCSRA |= (1<<ADSC);
  113. while (ADCSRA & (1<<ADSC)) ;
  114. low = ADCL;
  115. high = ADCH;
  116. return (high << 8) | low;
  117. }
  118. #define PIN_REG_AND_MASK_LOOKUP(pin, reg, mask) \
  119. asm volatile( \
  120. "lsl %2" "\n\t" \
  121. "add %A3, %2" "\n\t" \
  122. "adc %B3, __zero_reg__" "\n\n" \
  123. "lpm %1, Z+" "\n\t" \
  124. "lpm %A0, Z" "\n\t" \
  125. "ldi %B0, 0" "\n" \
  126. : "=z" (reg), "=r" (mask), "+r" (pin) \
  127. : "z" (digital_pin_table_PGM), "2" (pin))
  128. static const uint8_t didr_table_PGM[] PROGMEM = {
  129. (int)&DIDR0, ~0x01,
  130. (int)&DIDR0, ~0x02,
  131. (int)&DIDR0, ~0x04,
  132. (int)&DIDR0, ~0x08,
  133. (int)&DIDR0, ~0x10,
  134. (int)&DIDR0, ~0x20,
  135. (int)&DIDR0, ~0x40,
  136. (int)&DIDR0, 0x7F // ~0x80
  137. };
  138. #define PIN_DIDR_AND_MASK_LOOKUP(pin, didreg, didmask) \
  139. asm volatile( \
  140. "lsl %3" "\n\t" \
  141. "add %A2, %3" "\n\t" \
  142. "adc %B2, __zero_reg__" "\n\n" \
  143. "lpm %A0, Z+" "\n\t" \
  144. "ldi %B0, 0" "\n\t" \
  145. "lpm %1, Z+" "\n\t" \
  146. : "=x" (didreg), "=r" (didmask) \
  147. : "z" (didr_table_PGM), "r" (pin))
  148. const uint8_t digital_pin_table_PGM[] PROGMEM = {
  149. CORE_PIN0_BITMASK, (int)&CORE_PIN0_PINREG,
  150. CORE_PIN1_BITMASK, (int)&CORE_PIN1_PINREG,
  151. CORE_PIN2_BITMASK, (int)&CORE_PIN2_PINREG,
  152. CORE_PIN3_BITMASK, (int)&CORE_PIN3_PINREG,
  153. CORE_PIN4_BITMASK, (int)&CORE_PIN4_PINREG,
  154. CORE_PIN5_BITMASK, (int)&CORE_PIN5_PINREG,
  155. CORE_PIN6_BITMASK, (int)&CORE_PIN6_PINREG,
  156. CORE_PIN7_BITMASK, (int)&CORE_PIN7_PINREG,
  157. CORE_PIN8_BITMASK, (int)&CORE_PIN8_PINREG,
  158. CORE_PIN9_BITMASK, (int)&CORE_PIN9_PINREG,
  159. CORE_PIN10_BITMASK, (int)&CORE_PIN10_PINREG,
  160. CORE_PIN11_BITMASK, (int)&CORE_PIN11_PINREG,
  161. CORE_PIN12_BITMASK, (int)&CORE_PIN12_PINREG,
  162. CORE_PIN13_BITMASK, (int)&CORE_PIN13_PINREG,
  163. CORE_PIN14_BITMASK, (int)&CORE_PIN14_PINREG,
  164. CORE_PIN15_BITMASK, (int)&CORE_PIN15_PINREG,
  165. CORE_PIN16_BITMASK, (int)&CORE_PIN16_PINREG,
  166. CORE_PIN17_BITMASK, (int)&CORE_PIN17_PINREG,
  167. CORE_PIN18_BITMASK, (int)&CORE_PIN18_PINREG,
  168. CORE_PIN19_BITMASK, (int)&CORE_PIN19_PINREG,
  169. CORE_PIN20_BITMASK, (int)&CORE_PIN20_PINREG,
  170. #if CORE_NUM_TOTAL_PINS > 21
  171. CORE_PIN21_BITMASK, (int)&CORE_PIN21_PINREG,
  172. CORE_PIN22_BITMASK, (int)&CORE_PIN22_PINREG,
  173. CORE_PIN23_BITMASK, (int)&CORE_PIN23_PINREG,
  174. CORE_PIN24_BITMASK, (int)&CORE_PIN24_PINREG,
  175. #endif
  176. #if CORE_NUM_TOTAL_PINS > 25
  177. CORE_PIN25_BITMASK, (int)&CORE_PIN25_PINREG,
  178. CORE_PIN26_BITMASK, (int)&CORE_PIN26_PINREG,
  179. CORE_PIN27_BITMASK, (int)&CORE_PIN27_PINREG,
  180. CORE_PIN28_BITMASK, (int)&CORE_PIN28_PINREG,
  181. CORE_PIN29_BITMASK, (int)&CORE_PIN29_PINREG,
  182. CORE_PIN30_BITMASK, (int)&CORE_PIN30_PINREG,
  183. CORE_PIN31_BITMASK, (int)&CORE_PIN31_PINREG,
  184. CORE_PIN32_BITMASK, (int)&CORE_PIN32_PINREG,
  185. CORE_PIN33_BITMASK, (int)&CORE_PIN33_PINREG,
  186. CORE_PIN34_BITMASK, (int)&CORE_PIN34_PINREG,
  187. CORE_PIN35_BITMASK, (int)&CORE_PIN35_PINREG,
  188. CORE_PIN36_BITMASK, (int)&CORE_PIN36_PINREG,
  189. CORE_PIN37_BITMASK, (int)&CORE_PIN37_PINREG,
  190. CORE_PIN38_BITMASK, (int)&CORE_PIN38_PINREG,
  191. CORE_PIN39_BITMASK, (int)&CORE_PIN39_PINREG,
  192. CORE_PIN40_BITMASK, (int)&CORE_PIN40_PINREG,
  193. CORE_PIN41_BITMASK, (int)&CORE_PIN41_PINREG,
  194. CORE_PIN42_BITMASK, (int)&CORE_PIN42_PINREG,
  195. CORE_PIN43_BITMASK, (int)&CORE_PIN43_PINREG,
  196. CORE_PIN44_BITMASK, (int)&CORE_PIN44_PINREG,
  197. CORE_PIN45_BITMASK, (int)&CORE_PIN45_PINREG
  198. #endif
  199. };
  200. static void disable_peripherals(void) __attribute__((noinline));
  201. static void disable_peripherals(void)
  202. {
  203. EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
  204. TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
  205. DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
  206. PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
  207. }
  208. void _reboot_Teensyduino_(void)
  209. {
  210. cli();
  211. delayMicroseconds(5000);
  212. UDCON = 1;
  213. USBCON = (1<<FRZCLK);
  214. delayMicroseconds(15000);
  215. disable_peripherals();
  216. asm volatile("jmp 0");
  217. //__builtin_unreachable(); // available in gcc 4.5
  218. while (1) ;
  219. }
  220. void _restart_Teensyduino_(void)
  221. {
  222. cli();
  223. disable_peripherals(); // but leave USB intact
  224. delayMicroseconds(15000);
  225. asm volatile("jmp 0");
  226. //__builtin_unreachable(); // available in gcc 4.5
  227. while (1) ;
  228. }
  229. #if F_CPU == 16000000L
  230. #define TIMER0_MILLIS_INC 1
  231. #define TIMER0_FRACT_INC 3
  232. #define TIMER0_MICROS_INC 4
  233. #elif F_CPU == 8000000L
  234. #define TIMER0_MILLIS_INC 2
  235. #define TIMER0_FRACT_INC 6
  236. #define TIMER0_MICROS_INC 8
  237. #elif F_CPU == 4000000L
  238. #define TIMER0_MILLIS_INC 4
  239. #define TIMER0_FRACT_INC 12
  240. #define TIMER0_MICROS_INC 16
  241. #elif F_CPU == 2000000L
  242. #define TIMER0_MILLIS_INC 8
  243. #define TIMER0_FRACT_INC 24
  244. #define TIMER0_MICROS_INC 32
  245. #elif F_CPU == 1000000L
  246. #define TIMER0_MILLIS_INC 16
  247. #define TIMER0_FRACT_INC 48
  248. #define TIMER0_MICROS_INC 64
  249. #endif
  250. volatile unsigned long timer0_micros_count = 0;
  251. volatile unsigned long timer0_millis_count = 0;
  252. volatile unsigned char timer0_fract_count = 0;
  253. void TIMER0_OVF_vect() __attribute__((naked));
  254. void TIMER0_OVF_vect()
  255. {
  256. asm volatile(
  257. "push r24" "\n\t"
  258. "in r24, __SREG__" "\n\t"
  259. "push r24" "\n\t"
  260. "lds r24, timer0_fract_count" "\n\t"
  261. "subi r24, 256 - %0" "\n\t"
  262. "cpi r24, 125" "\n\t"
  263. "brsh L_%=_fract_roll" "\n\t"
  264. "L_%=_fract_noroll:" "\n\t"
  265. "sts timer0_fract_count, r24" "\n\t"
  266. "lds r24, timer0_millis_count" "\n\t"
  267. "subi r24, 256 - %1" "\n\t"
  268. "sts timer0_millis_count, r24" "\n\t"
  269. "brcs L_%=_ovcount" "\n\t"
  270. "L_%=_millis_inc_sext:"
  271. "lds r24, timer0_millis_count+1" "\n\t"
  272. "sbci r24, 255" "\n\t"
  273. "sts timer0_millis_count+1, r24" "\n\t"
  274. "brcs L_%=_ovcount" "\n\t"
  275. "lds r24, timer0_millis_count+2" "\n\t"
  276. "sbci r24, 255" "\n\t"
  277. "sts timer0_millis_count+2, r24" "\n\t"
  278. "brcs L_%=_ovcount" "\n\t"
  279. "lds r24, timer0_millis_count+3" "\n\t"
  280. "sbci r24, 255" "\n\t"
  281. "sts timer0_millis_count+3, r24" "\n\t"
  282. "rjmp L_%=_ovcount" "\n\t"
  283. "L_%=_fract_roll:" "\n\t"
  284. "subi r24, 125" "\n\t"
  285. "sts timer0_fract_count, r24" "\n\t"
  286. "lds r24, timer0_millis_count" "\n\t"
  287. "subi r24, 256 - %1 - 1" "\n\t"
  288. "sts timer0_millis_count, r24" "\n\t"
  289. "brcc L_%=_millis_inc_sext" "\n\t"
  290. "L_%=_ovcount:"
  291. "lds r24, timer0_micros_count" "\n\t"
  292. "subi r24, 256 - %2" "\n\t"
  293. "sts timer0_micros_count, r24" "\n\t"
  294. "brcs L_%=_end" "\n\t"
  295. "lds r24, timer0_micros_count+1" "\n\t"
  296. "sbci r24, 255" "\n\t"
  297. "sts timer0_micros_count+1, r24" "\n\t"
  298. "brcs L_%=_end" "\n\t"
  299. "lds r24, timer0_micros_count+2" "\n\t"
  300. "sbci r24, 255" "\n\t"
  301. "sts timer0_micros_count+2, r24" "\n\t"
  302. "L_%=_end:"
  303. "pop r24" "\n\t"
  304. "out __SREG__, r24" "\n\t"
  305. "pop r24" "\n\t"
  306. "reti"
  307. :
  308. : "M" (TIMER0_FRACT_INC), "M" (TIMER0_MILLIS_INC),
  309. "M" (TIMER0_MICROS_INC)
  310. );
  311. }
  312. void delay(uint32_t ms)
  313. {
  314. uint16_t start = (uint16_t)micros();
  315. while (ms > 0) {
  316. if (((uint16_t)micros() - start) >= 1000) {
  317. ms--;
  318. start += 1000;
  319. }
  320. }
  321. #if 0
  322. // This doesn't save a lot of power on Teensy, which
  323. // lacks the power saving flash memory of some newer
  324. // chips, and also usually consumes lots of power for
  325. // the USB port. There is also some strange (probably
  326. // hardware) bug involving the A/D mux for the first
  327. // conversion after the processor wakes from idle mode.
  328. uint32_t start;
  329. if (!(SREG & 0x80)) {
  330. // if interrupts are disabled, busy loop
  331. while (ms--) delayMicroseconds(1000);
  332. return;
  333. }
  334. // if interrupt are enabled, use low power idle mode
  335. cli();
  336. start = timer0_millis_count;
  337. do {
  338. _SLEEP_CONTROL_REG = SLEEP_MODE_IDLE | _SLEEP_ENABLE_MASK;
  339. sei();
  340. sleep_cpu();
  341. _SLEEP_CONTROL_REG = SLEEP_MODE_IDLE;
  342. cli();
  343. } while (timer0_millis_count - start <= ms);
  344. sei();
  345. #endif
  346. }
  347. uint32_t _micros(void)
  348. {
  349. register uint32_t out asm("r22");
  350. asm volatile(
  351. "in __tmp_reg__, __SREG__" "\n\t"
  352. "cli" "\n\t"
  353. "in %A0, %2" "\n\t"
  354. "in __zero_reg__, %3" "\n\t"
  355. "lds %B0, timer0_micros_count" "\n\t"
  356. "lds %C0, timer0_micros_count+1" "\n\t"
  357. "lds %D0, timer0_micros_count+2" "\n\t"
  358. "out __SREG__, __tmp_reg__" "\n\t"
  359. "sbrs __zero_reg__, %4" "\n\t"
  360. "rjmp L_%=_skip" "\n\t"
  361. "cpi %A0, 255" "\n\t"
  362. "breq L_%=_skip" "\n\t"
  363. "subi %B0, 256 - %1" "\n\t"
  364. "sbci %C0, 255" "\n\t"
  365. "sbci %D0, 255" "\n\t"
  366. "L_%=_skip:"
  367. "clr __zero_reg__" "\n\t"
  368. "clr __tmp_reg__" "\n\t"
  369. #if F_CPU == 16000000L || F_CPU == 8000000L || F_CPU == 4000000L
  370. "lsl %A0" "\n\t"
  371. "rol __tmp_reg__" "\n\t"
  372. "lsl %A0" "\n\t"
  373. "rol __tmp_reg__" "\n\t"
  374. #if F_CPU == 8000000L || F_CPU == 4000000L
  375. "lsl %A0" "\n\t"
  376. "rol __tmp_reg__" "\n\t"
  377. #endif
  378. #if F_CPU == 4000000L
  379. "lsl %A0" "\n\t"
  380. "rol __tmp_reg__" "\n\t"
  381. #endif
  382. "or %B0, __tmp_reg__" "\n\t"
  383. #endif
  384. #if F_CPU == 1000000L || F_CPU == 2000000L
  385. "lsr %A0" "\n\t"
  386. "ror __tmp_reg__" "\n\t"
  387. "lsr %A0" "\n\t"
  388. "ror __tmp_reg__" "\n\t"
  389. #if F_CPU == 2000000L
  390. "lsr %A0" "\n\t"
  391. "ror __tmp_reg__" "\n\t"
  392. #endif
  393. "or %B0, %A0" "\n\t"
  394. "mov %A0, __tmp_reg__" "\n\t"
  395. #endif
  396. : "=d" (out)
  397. : "M" (TIMER0_MICROS_INC),
  398. "I" (_SFR_IO_ADDR(TCNT0)),
  399. "I" (_SFR_IO_ADDR(TIFR0)),
  400. "I" (TOV0)
  401. : "r0"
  402. );
  403. return out;
  404. }