/** * Marlin 3D Printer Firmware * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * Based on Sprinter and grbl. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #pragma once /** * Fast I/O Routines for SAM3X8E * Use direct port manipulation to save scads of processor time. * Contributed by Triffid_Hunter and modified by Kliment, thinkyhead, Bob-the-Kuhn, et.al. */ /** * Description: Fast IO functions for Arduino Due and compatible (SAM3X8E) * * For ARDUINO_ARCH_SAM * Note the code here was specifically crafted by disassembling what GCC produces * out of it, so GCC is able to optimize it out as much as possible to the least * amount of instructions. Be very careful if you modify them, as "clean code" * leads to less efficient compiled code!! */ #include #include "../../inc/MarlinConfigPre.h" /** * Utility functions */ // Due has 12 PWMs assigned to logical pins 2-13. // 6, 7, 8 & 9 come from the PWM controller. The others come from the timers. #define PWM_PIN(P) WITHIN(P, 2, 13) #ifndef MASK #define MASK(PIN) _BV(PIN) #endif /** * Magic I/O routines * * Now you can simply SET_OUTPUT(STEP); WRITE(STEP, HIGH); WRITE(STEP, LOW); * * Why double up on these macros? see https://gcc.gnu.org/onlinedocs/cpp/Stringification.html */ // Read a pin #define _READ(IO) bool(DIO ## IO ## _WPORT -> PIO_PDSR & MASK(DIO ## IO ## _PIN)) // Write to a pin #define _WRITE(IO,V) do { \ volatile Pio* port = (DIO ## IO ## _WPORT); \ const uint32_t mask = MASK(DIO ## IO ## _PIN); \ if (V) port->PIO_SODR = mask; \ else port->PIO_CODR = mask; \ }while(0) // Toggle a pin #define _TOGGLE(IO) _WRITE(IO, !READ(IO)) #if MB(PRINTRBOARD_G2) #include "fastio/G2_pins.h" // Set pin as input #define _SET_INPUT(IO) do{ \ pmc_enable_periph_clk(G2_g_APinDescription[IO].ulPeripheralId); \ PIO_Configure((DIO ## IO ## _WPORT), PIO_INPUT, MASK(DIO ## IO ## _PIN), 0); \ }while(0) // Set pin as output #define _SET_OUTPUT(IO) do{ \ uint32_t mask = MASK(G2_g_APinDescription[IO].ulPeripheralId); \ if ((PMC->PMC_PCSR0 & mask) != (mask)) PMC->PMC_PCER0 = mask; \ volatile Pio* port = (DIO ## IO ## _WPORT); \ mask = MASK(DIO ## IO ## _PIN); \ if (_READ(IO)) port->PIO_SODR = mask; \ else port->PIO_CODR = mask; \ port->PIO_IDR = mask; \ const uint32_t pin_config = G2_g_APinDescription[IO].ulPinConfiguration; \ if (pin_config & PIO_PULLUP) port->PIO_PUER = mask; \ else port->PIO_PUDR = mask; \ if (pin_config & PIO_OPENDRAIN) port->PIO_MDER = mask; \ else port->PIO_MDDR = mask; \ port->PIO_PER = mask; \ port->PIO_OER = mask; \ g_pinStatus[IO] = (g_pinStatus[IO] & 0xF0) | PIN_STATUS_DIGITAL_OUTPUT; \ }while(0) /** * Set pin as output with comments * #define _SET_OUTPUT(IO) do{ \ * uint32_t mask = MASK(G2_g_APinDescription[IO].ulPeripheralId); \ * if ((PMC->PMC_PCSR0 & mask ) != (mask)) PMC->PMC_PCER0 = mask; \ // enable PIO clock if not already enabled * * volatile Pio* port = (DIO ## IO ## _WPORT); \ * const uint32_t mask = MASK(DIO ## IO ## _PIN); \ * if (_READ(IO)) port->PIO_SODR = mask; \ // set output to match input BEFORE setting direction or will glitch the output * else port->PIO_CODR = mask; \ * * port->PIO_IDR = mask; \ // disable interrupt * * uint32_t pin_config = G2_g_APinDescription[IO].ulPinConfiguration; \ * if (pin_config & PIO_PULLUP) pPio->PIO_PUER = mask; \ // enable pullup if necessary * else pPio->PIO_PUDR = mask; \ * * if (pin_config & PIO_OPENDRAIN) port->PIO_MDER = mask; \ // Enable multi-drive if necessary * else port->PIO_MDDR = mask; \ * * port->PIO_PER = mask; \ * port->PIO_OER = mask; \ // set to output * * g_pinStatus[IO] = (g_pinStatus[IO] & 0xF0) | PIN_STATUS_DIGITAL_OUTPUT; \ * }while(0) */ #else // Set pin as input #define _SET_INPUT(IO) do{ \ pmc_enable_periph_clk(g_APinDescription[IO].ulPeripheralId); \ PIO_Configure(digitalPinToPort(IO), PIO_INPUT, digitalPinToBitMask(IO), 0); \ }while(0) // Set pin as output #define _SET_OUTPUT(IO) do{ \ pmc_enable_periph_clk(g_APinDescription[IO].ulPeripheralId); \ PIO_Configure(digitalPinToPort(IO), _READ(IO) ? PIO_OUTPUT_1 : PIO_OUTPUT_0, digitalPinToBitMask(IO), g_APinDescription[IO].ulPinConfiguration); \ g_pinStatus[IO] = (g_pinStatus[IO] & 0xF0) | PIN_STATUS_DIGITAL_OUTPUT; \ }while(0) #endif // Set pin as input with pullup mode #define _PULLUP(IO,V) pinMode(IO, (V) ? INPUT_PULLUP : INPUT) // Read a pin (wrapper) #define READ(IO) _READ(IO) // Write to a pin (wrapper) #define WRITE(IO,V) _WRITE(IO,V) // Toggle a pin (wrapper) #define TOGGLE(IO) _TOGGLE(IO) // Set pin as input (wrapper) #define SET_INPUT(IO) _SET_INPUT(IO) // Set pin as input with pullup (wrapper) #define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _PULLUP(IO, HIGH); }while(0) // Set pin as input with pulldown (substitution) #define SET_INPUT_PULLDOWN SET_INPUT // Set pin as output (wrapper) - reads the pin and sets the output to that value #define SET_OUTPUT(IO) _SET_OUTPUT(IO) // Set pin as PWM #define SET_PWM SET_OUTPUT // Check if pin is an input #define IS_INPUT(IO) ((digitalPinToPort(IO)->PIO_OSR & digitalPinToBitMask(IO)) == 0) // Check if pin is an output #define IS_OUTPUT(IO) ((digitalPinToPort(IO)->PIO_OSR & digitalPinToBitMask(IO)) != 0) // Shorthand #define OUT_WRITE(IO,V) do{ SET_OUTPUT(IO); WRITE(IO,V); }while(0) // digitalRead/Write wrappers #define extDigitalRead(IO) digitalRead(IO) #define extDigitalWrite(IO,V) digitalWrite(IO,V) /** * Ports and functions * Added as necessary or if I feel like it- not a comprehensive list! */ // UART #define RXD DIO0 #define TXD DIO1 // TWI (I2C) #define SCL DIO21 #define SDA DIO20 /** * pins */ #define DIO0_PIN 8 #define DIO0_WPORT PIOA #define DIO1_PIN 9 #define DIO1_WPORT PIOA #define DIO2_PIN 25 #define DIO2_WPORT PIOB #define DIO3_PIN 28 #define DIO3_WPORT PIOC #define DIO4_PIN 26 #define DIO4_WPORT PIOC #define DIO5_PIN 25 #define DIO5_WPORT PIOC #define DIO6_PIN 24 #define DIO6_WPORT PIOC #define DIO7_PIN 23 #define DIO7_WPORT PIOC #define DIO8_PIN 22 #define DIO8_WPORT PIOC #define DIO9_PIN 21 #define DIO9_WPORT PIOC #define DIO10_PIN 29 #define DIO10_WPORT PIOC #define DIO11_PIN 7 #define DIO11_WPORT PIOD #define DIO12_PIN 8 #define DIO12_WPORT PIOD #define DIO13_PIN 27 #define DIO13_WPORT PIOB #define DIO14_PIN 4 #define DIO14_WPORT PIOD #define DIO15_PIN 5 #define DIO15_WPORT PIOD #define DIO16_PIN 13 #define DIO16_WPORT PIOA #define DIO17_PIN 12 #define DIO17_WPORT PIOA #define DIO18_PIN 11 #define DIO18_WPORT PIOA #define DIO19_PIN 10 #define DIO19_WPORT PIOA #define DIO20_PIN 12 #define DIO20_WPORT PIOB #define DIO21_PIN 13 #define DIO21_WPORT PIOB #define DIO22_PIN 26 #define DIO22_WPORT PIOB #define DIO23_PIN 14 #define DIO23_WPORT PIOA #define DIO24_PIN 15 #define DIO24_WPORT PIOA #define DIO25_PIN 0 #define DIO25_WPORT PIOD #define DIO26_PIN 1 #define DIO26_WPORT PIOD #define DIO27_PIN 2 #define DIO27_WPORT PIOD #define DIO28_PIN 3 #define DIO28_WPORT PIOD #define DIO29_PIN 6 #define DIO29_WPORT PIOD #define DIO30_PIN 9 #define DIO30_WPORT PIOD #define DIO31_PIN 7 #define DIO31_WPORT PIOA #define DIO32_PIN 10 #define DIO32_WPORT PIOD #define DIO33_PIN 1 #define DIO33_WPORT PIOC #if !MB(PRINTRBOARD_G2) // normal DUE pin mapping #define DIO34_PIN 2 #define DIO34_WPORT PIOC #define DIO35_PIN 3 #define DIO35_WPORT PIOC #define DIO36_PIN 4 #define DIO36_WPORT PIOC #define DIO37_PIN 5 #define DIO37_WPORT PIOC #define DIO38_PIN 6 #define DIO38_WPORT PIOC #define DIO39_PIN 7 #define DIO39_WPORT PIOC #define DIO40_PIN 8 #define DIO40_WPORT PIOC #define DIO41_PIN 9 #define DIO41_WPORT PIOC #endif // !PRINTRBOARD_G2 #define DIO42_PIN 19 #define DIO42_WPORT PIOA #define DIO43_PIN 20 #define DIO43_WPORT PIOA #define DIO44_PIN 19 #define DIO44_WPORT PIOC #define DIO45_PIN 18 #define DIO45_WPORT PIOC #define DIO46_PIN 17 #define DIO46_WPORT PIOC #define DIO47_PIN 16 #define DIO47_WPORT PIOC #define DIO48_PIN 15 #define DIO48_WPORT PIOC #define DIO49_PIN 14 #define DIO49_WPORT PIOC #define DIO50_PIN 13 #define DIO50_WPORT PIOC #define DIO51_PIN 12 #define DIO51_WPORT PIOC #define DIO52_PIN 21 #define DIO52_WPORT PIOB #define DIO53_PIN 14 #define DIO53_WPORT PIOB #define DIO54_PIN 16 #define DIO54_WPORT PIOA #define DIO55_PIN 24 #define DIO55_WPORT PIOA #define DIO56_PIN 23 #define DIO56_WPORT PIOA #define DIO57_PIN 22 #define DIO57_WPORT PIOA #define DIO58_PIN 6 #define DIO58_WPORT PIOA #define DIO59_PIN 4 #define DIO59_WPORT PIOA #define DIO60_PIN 3 #define DIO60_WPORT PIOA #define DIO61_PIN 2 #define DIO61_WPORT PIOA #define DIO62_PIN 17 #define DIO62_WPORT PIOB #define DIO63_PIN 18 #define DIO63_WPORT PIOB #define DIO64_PIN 19 #define DIO64_WPORT PIOB #define DIO65_PIN 20 #define DIO65_WPORT PIOB #define DIO66_PIN 15 #define DIO66_WPORT PIOB #define DIO67_PIN 16 #define DIO67_WPORT PIOB #define DIO68_PIN 1 #define DIO68_WPORT PIOA #define DIO69_PIN 0 #define DIO69_WPORT PIOA #define DIO70_PIN 17 #define DIO70_WPORT PIOA #define DIO71_PIN 18 #define DIO71_WPORT PIOA #define DIO72_PIN 30 #define DIO72_WPORT PIOC #define DIO73_PIN 21 #define DIO73_WPORT PIOA #define DIO74_PIN 25 #define DIO74_WPORT PIOA #define DIO75_PIN 26 #define DIO75_WPORT PIOA #define DIO76_PIN 27 #define DIO76_WPORT PIOA #define DIO77_PIN 28 #define DIO77_WPORT PIOA #define DIO78_PIN 23 #define DIO78_WPORT PIOB #define DIO79_PIN 17 #define DIO79_WPORT PIOA #define DIO80_PIN 12 #define DIO80_WPORT PIOB #define DIO81_PIN 8 #define DIO81_WPORT PIOA #define DIO82_PIN 11 #define DIO82_WPORT PIOA #define DIO83_PIN 13 #define DIO83_WPORT PIOA #define DIO84_PIN 4 #define DIO84_WPORT PIOD #define DIO85_PIN 11 #define DIO85_WPORT PIOB #define DIO86_PIN 21 #define DIO86_WPORT PIOB #define DIO87_PIN 29 #define DIO87_WPORT PIOA #define DIO88_PIN 15 #define DIO88_WPORT PIOB #define DIO89_PIN 14 #define DIO89_WPORT PIOB #define DIO90_PIN 1 #define DIO90_WPORT PIOA #define DIO91_PIN 15 #define DIO91_WPORT PIOB #ifdef ARDUINO_SAM_ARCHIM #define DIO92_PIN 11 #define DIO92_WPORT PIOC #define DIO93_PIN 2 #define DIO93_WPORT PIOB #define DIO94_PIN 1 #define DIO94_WPORT PIOB #define DIO95_PIN 0 #define DIO95_WPORT PIOB #define DIO96_PIN 10 #define DIO96_WPORT PIOC #define DIO97_PIN 24 #define DIO97_WPORT PIOB #define DIO98_PIN 7 #define DIO98_WPORT PIOB #define DIO99_PIN 6 #define DIO99_WPORT PIOB #define DIO100_PIN 8 #define DIO100_WPORT PIOB #define DIO101_PIN 5 #define DIO101_WPORT PIOB #define DIO102_PIN 4 #define DIO102_WPORT PIOB #define DIO103_PIN 3 #define DIO103_WPORT PIOB #define DIO104_PIN 20 #define DIO104_WPORT PIOC #define DIO105_PIN 22 #define DIO105_WPORT PIOB #define DIO106_PIN 27 #define DIO106_WPORT PIOC #define DIO107_PIN 10 #define DIO107_WPORT PIOB #define DIO108_PIN 9 #define DIO108_WPORT PIOB #else // !ARDUINO_SAM_ARCHIM #define DIO92_PIN 5 #define DIO92_WPORT PIOA #define DIO93_PIN 12 #define DIO93_WPORT PIOB #define DIO94_PIN 22 #define DIO94_WPORT PIOB #define DIO95_PIN 23 #define DIO95_WPORT PIOB #define DIO96_PIN 24 #define DIO96_WPORT PIOB #define DIO97_PIN 20 #define DIO97_WPORT PIOC #define DIO98_PIN 27 #define DIO98_WPORT PIOC #define DIO99_PIN 10 #define DIO99_WPORT PIOC #define DIO100_PIN 11 #define DIO100_WPORT PIOC #endif // !ARDUINO_SAM_ARCHIM