Adafruit Grand Central M4 (#14749)

2.0.x
Giuliano Zaro 5 years ago committed by Scott Lahteine
parent fec52e61ea
commit 290466578f

@ -19,6 +19,7 @@ env:
- TEST_PLATFORM="esp32"
- TEST_PLATFORM="alfawise_U20"
- TEST_PLATFORM="black_stm32f407ve"
- TEST_PLATFORM="adafruit_grandcentral_m4"
before_install:
#

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -41,6 +41,8 @@
#define HAL_PLATFORM HAL_ESP32
#elif defined(__PLAT_LINUX__)
#define HAL_PLATFORM HAL_LINUX
#elif defined(__SAMD51__)
#define HAL_PLATFORM HAL_SAMD51
#else
#error "Unsupported Platform!"
#endif

@ -0,0 +1,475 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifdef __SAMD51__
#include "../../inc/MarlinConfig.h"
#include "Adafruit_ZeroDMA.h"
#include "wiring_private.h"
// ------------------------
// Local defines
// ------------------------
#if HAS_TEMP_ADC_0
#define GET_TEMP_0_ADC() PIN_TO_ADC(TEMP_0_PIN)
#else
#define GET_TEMP_0_ADC() -1
#endif
#if HAS_TEMP_ADC_1
#define GET_TEMP_1_ADC() PIN_TO_ADC(TEMP_1_PIN)
#else
#define GET_TEMP_1_ADC() -1
#endif
#if HAS_TEMP_ADC_2
#define GET_TEMP_2_ADC() PIN_TO_ADC(TEMP_2_PIN)
#else
#define GET_TEMP_2_ADC() -1
#endif
#if HAS_TEMP_ADC_3
#define GET_TEMP_3_ADC() PIN_TO_ADC(TEMP_3_PIN)
#else
#define GET_TEMP_3_ADC() -1
#endif
#if HAS_TEMP_ADC_4
#define GET_TEMP_4_ADC() PIN_TO_ADC(TEMP_4_PIN)
#else
#define GET_TEMP_4_ADC() -1
#endif
#if HAS_TEMP_ADC_5
#define GET_TEMP_5_ADC() PIN_TO_ADC(TEMP_5_PIN)
#else
#define GET_TEMP_5_ADC() -1
#endif
#if HAS_HEATED_BED
#define GET_BED_ADC() PIN_TO_ADC(TEMP_BED_PIN)
#else
#define GET_BED_ADC() -1
#endif
#if HAS_HEATED_CHAMBER
#define GET_CHAMBER_ADC() PIN_TO_ADC(TEMP_CHAMBER_PIN)
#else
#define GET_CHAMBER_ADC() -1
#endif
#if ENABLED(FILAMENT_WIDTH_SENSOR)
#define GET_FILAMENT_WIDTH_ADC() PIN_TO_ADC(FILWIDTH_PIN)
#else
#define GET_FILAMENT_WIDTH_ADC() -1
#endif
#if HAS_ADC_BUTTONS
#define GET_BUTTONS_ADC() PIN_TO_ADC(ADC_KEYPAD_PIN)
#else
#define GET_BUTTONS_ADC() -1
#endif
#define IS_ADC_REQUIRED(n) (GET_TEMP_0_ADC() == n || GET_TEMP_1_ADC() == n || GET_TEMP_2_ADC() == n \
|| GET_TEMP_3_ADC() == n || GET_TEMP_4_ADC() == n || GET_TEMP_5_ADC() == n \
|| GET_BED_ADC() == n \
|| GET_CHAMBER_ADC() == n \
|| GET_FILAMENT_WIDTH_ADC() == n \
|| GET_BUTTONS_ADC() == n)
#define ADC0_IS_REQUIRED IS_ADC_REQUIRED(0)
#define ADC1_IS_REQUIRED IS_ADC_REQUIRED(1)
#define ADC_IS_REQUIRED (ADC0_IS_REQUIRED || ADC1_IS_REQUIRED)
#if ADC0_IS_REQUIRED
#define FIRST_ADC 0
#else
#define FIRST_ADC 1
#endif
#if ADC1_IS_REQUIRED
#define LAST_ADC 1
#else
#define LAST_ADC 0
#endif
#define DMA_IS_REQUIRED ADC_IS_REQUIRED
// ------------------------
// Types
// ------------------------
#if DMA_IS_REQUIRED
// Struct must be 32 bits aligned because of DMA accesses but fields needs to be 8 bits packed
typedef struct __attribute__((aligned(4), packed)) {
ADC_INPUTCTRL_Type INPUTCTRL;
} HAL_DMA_DAC_Registers; // DMA transfered registers
#endif
// ------------------------
// Private Variables
// ------------------------
uint16_t HAL_adc_result;
#if ADC_IS_REQUIRED
// Pins used by ADC inputs. Order must be ADC0 inputs first then ADC1
const uint8_t adc_pins[] = {
// ADC0 pins
#if GET_TEMP_0_ADC() == 0
TEMP_0_PIN,
#endif
#if GET_TEMP_1_ADC() == 0
TEMP_1_PIN,
#endif
#if GET_TEMP_2_ADC() == 0
TEMP_2_PIN,
#endif
#if GET_TEMP_3_ADC() == 0
TEMP_3_PIN,
#endif
#if GET_TEMP_4_ADC() == 0
TEMP_4_PIN,
#endif
#if GET_TEMP_5_ADC() == 0
TEMP_5_PIN,
#endif
#if GET_BED_ADC() == 0
TEMP_BED_PIN,
#endif
#if GET_CHAMBER_ADC() == 0
TEMP_CHAMBER_PIN,
#endif
#if GET_FILAMENT_WIDTH_ADC() == 0
FILWIDTH_PIN,
#endif
#if GET_BUTTONS_ADC() == 0
ADC_KEYPAD_PIN,
#endif
// ADC1 pins
#if GET_TEMP_0_ADC() == 1
TEMP_0_PIN,
#endif
#if GET_TEMP_1_ADC() == 1
TEMP_1_PIN,
#endif
#if GET_TEMP_2_ADC() == 1
TEMP_2_PIN,
#endif
#if GET_TEMP_3_ADC() == 1
TEMP_3_PIN,
#endif
#if GET_TEMP_4_ADC() == 1
TEMP_4_PIN,
#endif
#if GET_TEMP_5_ADC() == 1
TEMP_5_PIN,
#endif
#if GET_BED_ADC() == 1
TEMP_BED_PIN,
#endif
#if GET_CHAMBER_ADC() == 1
TEMP_CHAMBER_PIN,
#endif
#if GET_FILAMENT_WIDTH_ADC() == 1
FILWIDTH_PIN,
#endif
#if GET_BUTTONS_ADC() == 1
ADC_KEYPAD_PIN,
#endif
};
uint16_t HAL_adc_results[COUNT(adc_pins)];
#if ADC0_IS_REQUIRED
Adafruit_ZeroDMA adc0ProgramDMA,
adc0ReadDMA;
const HAL_DMA_DAC_Registers adc0_dma_regs_list[] = {
#if GET_TEMP_0_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_0_PIN) },
#endif
#if GET_TEMP_1_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_1_PIN) },
#endif
#if GET_TEMP_2_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_2_PIN) },
#endif
#if GET_TEMP_3_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_3_PIN) },
#endif
#if GET_TEMP_4_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_4_PIN) },
#endif
#if GET_TEMP_5_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_5_PIN) },
#endif
#if GET_BED_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_BED_PIN) },
#endif
#if GET_CHAMBER_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
#endif
#if GET_FILAMENT_WIDTH_ADC() == 0
{ PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
#endif
#if GET_BUTTONS_ADC() == 0
{ PIN_TO_INPUTCTRL(ADC_KEYPAD_PIN) },
#endif
};
#define ADC0_AINCOUNT COUNT(adc0_dma_regs_list)
#endif // ADC0_IS_REQUIRED
#if ADC1_IS_REQUIRED
Adafruit_ZeroDMA adc1ProgramDMA,
adc1ReadDMA;
const HAL_DMA_DAC_Registers adc1_dma_regs_list[] = {
#if GET_TEMP_0_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_0_PIN) },
#endif
#if GET_TEMP_1_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_1_PIN) },
#endif
#if GET_TEMP_2_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_2_PIN) },
#endif
#if GET_TEMP_3_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_3_PIN) },
#endif
#if GET_TEMP_4_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_4_PIN) },
#endif
#if GET_TEMP_5_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_5_PIN) },
#endif
#if GET_BED_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_BED_PIN) },
#endif
#if GET_CHAMBER_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
#endif
#if GET_FILAMENT_WIDTH_ADC() == 1
{ PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
#endif
#if GET_BUTTONS_ADC() == 1
{ PIN_TO_INPUTCTRL(ADC_KEYPAD_PIN) },
#endif
};
#define ADC1_AINCOUNT COUNT(adc1_dma_regs_list)
#endif // ADC1_IS_REQUIRED
#endif // ADC_IS_REQUIRED
// ------------------------
// Private functions
// ------------------------
#if DMA_IS_REQUIRED
void dma_init() {
DmacDescriptor *descriptor;
#if ADC0_IS_REQUIRED
adc0ProgramDMA.setTrigger(ADC0_DMAC_ID_SEQ);
adc0ProgramDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
adc0ProgramDMA.loop(true);
if (adc0ProgramDMA.allocate() == DMA_STATUS_OK) {
descriptor = adc0ProgramDMA.addDescriptor(
(void *)adc0_dma_regs_list, // SRC
(void *)&ADC0->DSEQDATA.reg, // DEST
sizeof(adc0_dma_regs_list) / 4, // CNT
DMA_BEAT_SIZE_WORD,
true, // SRCINC
false, // DSTINC
DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
DMA_STEPSEL_SRC // STEPSEL
);
if (descriptor != nullptr)
descriptor->BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_BEAT;
adc0ProgramDMA.startJob();
}
adc0ReadDMA.setTrigger(ADC0_DMAC_ID_RESRDY);
adc0ReadDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
adc0ReadDMA.loop(true);
if (adc0ReadDMA.allocate() == DMA_STATUS_OK) {
adc0ReadDMA.addDescriptor(
(void *)&ADC0->RESULT.reg, // SRC
&HAL_adc_results, // DEST
ADC0_AINCOUNT, // CNT
DMA_BEAT_SIZE_HWORD,
false, // SRCINC
true, // DSTINC
DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
DMA_STEPSEL_DST // STEPSEL
);
adc0ReadDMA.startJob();
}
#endif
#if ADC1_IS_REQUIRED
adc1ProgramDMA.setTrigger(ADC1_DMAC_ID_SEQ);
adc1ProgramDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
adc1ProgramDMA.loop(true);
if (adc1ProgramDMA.allocate() == DMA_STATUS_OK) {
descriptor = adc1ProgramDMA.addDescriptor(
(void *)adc1_dma_regs_list, // SRC
(void *)&ADC1->DSEQDATA.reg, // DEST
sizeof(adc1_dma_regs_list) / 4, // CNT
DMA_BEAT_SIZE_WORD,
true, // SRCINC
false, // DSTINC
DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
DMA_STEPSEL_SRC // STEPSEL
);
if (descriptor != nullptr)
descriptor->BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_BEAT;
adc1ProgramDMA.startJob();
}
adc1ReadDMA.setTrigger(ADC1_DMAC_ID_RESRDY);
adc1ReadDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
adc1ReadDMA.loop(true);
if (adc1ReadDMA.allocate() == DMA_STATUS_OK) {
adc1ReadDMA.addDescriptor(
(void *)&ADC1->RESULT.reg, // SRC
&HAL_adc_results[ADC0_AINCOUNT], // DEST
ADC1_AINCOUNT, // CNT
DMA_BEAT_SIZE_HWORD,
false, // SRCINC
true, // DSTINC
DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
DMA_STEPSEL_DST // STEPSEL
);
adc1ReadDMA.startJob();
}
#endif
DMAC->PRICTRL0.bit.RRLVLEN0 = true; // Activate round robin for DMA channels used by ADCs
}
#endif // DMA_IS_REQUIRED
// ------------------------
// Public functions
// ------------------------
// HAL initialization task
void HAL_init(void) {
#if DMA_IS_REQUIRED
dma_init();
#endif
#if ENABLED(SDSUPPORT)
#if SD_CONNECTION_IS(ONBOARD) && PIN_EXISTS(SD_DETECT) // SD_DETECT_PIN may be remove when NO_SD_HOST_DRIVE is not defined in configuration_adv
SET_INPUT_PULLUP(SD_DETECT_PIN);
#endif
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
#endif
}
// HAL idle task
/*
void HAL_idletask(void) {
}
*/
void HAL_clear_reset_source(void) { }
#pragma push_macro("WDT")
#undef WDT // Required to be able to use '.bit.WDT'. Compiler wrongly replace struct field with WDT define
uint8_t HAL_get_reset_source(void) {
RSTC_RCAUSE_Type resetCause;
resetCause.reg = REG_RSTC_RCAUSE;
if (resetCause.bit.POR) return RST_POWER_ON;
else if (resetCause.bit.EXT) return RST_EXTERNAL;
else if (resetCause.bit.BODCORE || resetCause.bit.BODVDD) return RST_BROWN_OUT;
else if (resetCause.bit.WDT) return RST_WATCHDOG;
else if (resetCause.bit.SYST || resetCause.bit.NVM) return RST_SOFTWARE;
else if (resetCause.bit.BACKUP) return RST_BACKUP;
return 0;
}
#pragma pop_macro("WDT")
extern "C" {
void * _sbrk(int incr);
extern unsigned int __bss_end__; // end of bss section
}
// Return free memory between end of heap (or end bss) and whatever is current
int freeMemory() {
int free_memory, heap_end = (int)_sbrk(0);
return (int)&free_memory - (heap_end ? heap_end : (int)&__bss_end__);
}
// ------------------------
// ADC
// ------------------------
void HAL_adc_init(void) {
#if ADC_IS_REQUIRED
memset(HAL_adc_results, 0xFF, sizeof(HAL_adc_results)); // Fill result with invalid values
for (uint8_t pi = 0; pi < COUNT(adc_pins); ++pi)
pinPeripheral(adc_pins[pi], PIO_ANALOG);
for (uint8_t ai = FIRST_ADC; ai <= LAST_ADC; ++ai) {
Adc* adc = ((Adc*[])ADC_INSTS)[ai];
// ADC clock setup
GCLK->PCHCTRL[ADC0_GCLK_ID + ai].bit.CHEN = false;
SYNC(GCLK->PCHCTRL[ADC0_GCLK_ID + ai].bit.CHEN);
GCLK->PCHCTRL[ADC0_GCLK_ID + ai].reg = GCLK_PCHCTRL_GEN_GCLK1 | GCLK_PCHCTRL_CHEN; // 48MHz startup code programmed
SYNC(!GCLK->PCHCTRL[ADC0_GCLK_ID + ai].bit.CHEN);
adc->CTRLA.bit.PRESCALER = ADC_CTRLA_PRESCALER_DIV32_Val; // 1.5MHZ adc clock
// ADC setup
// Preloaded data (fixed for all ADC instances hence not loaded by DMA)
adc->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_AREFA_Val; // VRefA pin
SYNC(adc->SYNCBUSY.bit.REFCTRL);
adc->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val;
SYNC(adc->SYNCBUSY.bit.CTRLB);
adc->SAMPCTRL.bit.SAMPLEN = (6 - 1); // Sampling clocks
// Registers loaded by DMA
adc->DSEQCTRL.bit.INPUTCTRL = true;
adc->DSEQCTRL.bit.AUTOSTART = true; // Start conversion after DMA sequence
adc->CTRLA.bit.ENABLE = true; // Enable ADC
SYNC(adc->SYNCBUSY.bit.ENABLE);
}
#endif // ADC_IS_REQUIRED
}
void HAL_adc_start_conversion(const uint8_t adc_pin) {
#if ADC_IS_REQUIRED
for (uint8_t pi = 0; pi < COUNT(adc_pins); ++pi) {
if (adc_pin == adc_pins[pi]) {
HAL_adc_result = HAL_adc_results[pi];
return;
}
}
#endif
HAL_adc_result = 0xFFFF;
}
uint16_t HAL_adc_get_result(void) {
return HAL_adc_result;
}
#endif // __SAMD51__

@ -0,0 +1,141 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#define CPU_32_BIT
#include "../shared/Marduino.h"
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "fastio_SAMD51.h"
#include "watchdog_SAMD51.h"
#include "HAL_timers_SAMD51.h"
#ifdef ADAFRUIT_GRAND_CENTRAL_M4
#include "MarlinSerial_AGCM4.h"
// Serial ports
#if !WITHIN(SERIAL_PORT, -1, 3)
#error "SERIAL_PORT must be from -1 to 3"
#endif
// MYSERIAL0 required before MarlinSerial includes!
#if SERIAL_PORT == -1
#define MYSERIAL0 Serial
#elif SERIAL_PORT == 0
#define MYSERIAL0 Serial1
#elif SERIAL_PORT == 1
#define MYSERIAL0 Serial2
#elif SERIAL_PORT == 2
#define MYSERIAL0 Serial3
#else
#define MYSERIAL0 Serial4
#endif
#ifdef SERIAL_PORT_2
#if !WITHIN(SERIAL_PORT_2, -1, 3)
#error "SERIAL_PORT_2 must be from -1 to 3"
#elif SERIAL_PORT_2 == SERIAL_PORT
#error "SERIAL_PORT_2 must be different than SERIAL_PORT"
#endif
#define NUM_SERIAL 2
#if SERIAL_PORT_2 == -1
#define MYSERIAL1 Serial
#elif SERIAL_PORT_2 == 0
#define MYSERIAL1 Serial1
#elif SERIAL_PORT_2 == 1
#define MYSERIAL1 Serial2
#elif SERIAL_PORT_2 == 2
#define MYSERIAL1 Serial3
#else
#define MYSERIAL1 Serial4
#endif
#else
#define NUM_SERIAL 1
#endif
#endif // ADAFRUIT_GRAND_CENTRAL_M4
typedef int8_t pin_t;
//#define HAL_SERVO_LIB Servo
//
// Interrupts
//
#define CRITICAL_SECTION_START uint32_t primask = __get_PRIMASK(); __disable_irq()
#define CRITICAL_SECTION_END if (!primask) __enable_irq()
#define ISRS_ENABLED() (!__get_PRIMASK())
#define ENABLE_ISRS() __enable_irq()
#define DISABLE_ISRS() __disable_irq()
#define cli() __disable_irq() // Disable interrupts
#define sei() __enable_irq() // Enable interrupts
void HAL_clear_reset_source(void); // clear reset reason
uint8_t HAL_get_reset_source(void); // get reset reason
//
// EEPROM
//
void eeprom_write_byte(uint8_t *pos, unsigned char value);
uint8_t eeprom_read_byte(uint8_t *pos);
//
// ADC
//
extern uint16_t HAL_adc_result; // result of last ADC conversion
#define HAL_ANALOG_SELECT(pin)
void HAL_adc_init(void);
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
#define HAL_READ_ADC() HAL_adc_result
#define HAL_ADC_READY() true
void HAL_adc_start_conversion(const uint8_t adc_pin);
uint16_t HAL_adc_get_result(void);
//
// Pin Map
//
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
//
// Tone
//
void toneInit();
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0);
void noTone(const pin_t _pin);
// Enable hooks into idle and setup for HAL
void HAL_init(void);
/*#define HAL_IDLETASK 1
void HAL_idletask(void);*/
//
// Utility functions
//
FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); }
int freeMemory(void);

@ -0,0 +1,151 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
/**
* Hardware and software SPI implementations are included in this file.
*
* Control of the slave select pin(s) is handled by the calling routines and
* SAMD51 let hardware SPI handling to remove SS from its logic.
*/
#ifdef __SAMD51__
// --------------------------------------------------------------------------
// Includes
// --------------------------------------------------------------------------
#include "../../inc/MarlinConfig.h"
#include <SPI.h>
// --------------------------------------------------------------------------
// Public functions
// --------------------------------------------------------------------------
#if EITHER(SOFTWARE_SPI, FORCE_SOFT_SPI)
// ------------------------
// Software SPI
// ------------------------
#error "Software SPI not supported for SAMD51. Use Hardware SPI."
#if SD_CONNECTION_IS(ONBOARD)
#endif
#else // !SOFTWARE_SPI
#ifdef ADAFRUIT_GRAND_CENTRAL_M4
#if SD_CONNECTION_IS(ONBOARD)
#define sdSPI SDCARD_SPI
#else
#define sdSPI SPI
#endif
#endif
static SPISettings spiConfig;
// ------------------------
// Hardware SPI
// ------------------------
void spiBegin(void) {
spiInit(SPI_HALF_SPEED);
}
void spiInit(uint8_t spiRate) {
// Use datarates Marlin uses
uint32_t clock;
switch (spiRate) {
case SPI_FULL_SPEED: clock = 8000000; break;
case SPI_HALF_SPEED: clock = 4000000; break;
case SPI_QUARTER_SPEED: clock = 2000000; break;
case SPI_EIGHTH_SPEED: clock = 1000000; break;
case SPI_SIXTEENTH_SPEED: clock = 500000; break;
case SPI_SPEED_5: clock = 250000; break;
case SPI_SPEED_6: clock = 125000; break;
default: clock = 4000000; break; // Default from the SPI library
}
spiConfig = SPISettings(clock, MSBFIRST, SPI_MODE0);
sdSPI.begin();
}
/**
* @brief Receives a single byte from the SPI port.
*
* @return Byte received
*
* @details
*/
uint8_t spiRec(void) {
sdSPI.beginTransaction(spiConfig);
uint8_t returnByte = sdSPI.transfer(0xFF);
sdSPI.endTransaction();
return returnByte;
}
/**
* @brief Receives a number of bytes from the SPI port to a buffer
*
* @param buf Pointer to starting address of buffer to write to.
* @param nbyte Number of bytes to receive.
* @return Nothing
*/
void spiRead(uint8_t* buf, uint16_t nbyte) {
if (nbyte == 0) return;
memset(buf, 0xFF, nbyte);
sdSPI.beginTransaction(spiConfig);
sdSPI.transfer(buf, nbyte);
sdSPI.endTransaction();
}
/**
* @brief Sends a single byte on SPI port
*
* @param b Byte to send
*
* @details
*/
void spiSend(uint8_t b) {
sdSPI.beginTransaction(spiConfig);
sdSPI.transfer(b);
sdSPI.endTransaction();
}
/**
* @brief Write token and then write from 512 byte buffer to SPI (for SD card)
*
* @param buf Pointer with buffer start address
* @return Nothing
*
* @details Uses DMA
*/
void spiSendBlock(uint8_t token, const uint8_t* buf) {
sdSPI.beginTransaction(spiConfig);
sdSPI.transfer(token);
sdSPI.transfer((uint8_t*)buf, nullptr, 512);
sdSPI.endTransaction();
}
void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
spiConfig = SPISettings(spiClock, (BitOrder)bitOrder, dataMode);
sdSPI.beginTransaction(spiConfig);
}
#endif // !SOFTWARE_SPI
#endif // __SAMD51__

@ -0,0 +1,135 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifdef __SAMD51__
// --------------------------------------------------------------------------
// Includes
// --------------------------------------------------------------------------
#include "../../inc/MarlinConfig.h"
#include "HAL_timers_SAMD51.h"
// --------------------------------------------------------------------------
// Local defines
// --------------------------------------------------------------------------
#define NUM_HARDWARE_TIMERS 8
// --------------------------------------------------------------------------
// Private Variables
// --------------------------------------------------------------------------
const tTimerConfig TimerConfig[NUM_HARDWARE_TIMERS] = {
{ TC0, TC0_IRQn, TC_PRIORITY(0) },
{ TC1, TC1_IRQn, TC_PRIORITY(1) },
{ TC2, TC2_IRQn, TC_PRIORITY(2) },
{ TC3, TC3_IRQn, TC_PRIORITY(3) },
{ TC4, TC4_IRQn, TC_PRIORITY(4) },
{ TC5, TC5_IRQn, TC_PRIORITY(5) },
{ TC6, TC6_IRQn, TC_PRIORITY(6) },
{ TC7, TC7_IRQn, TC_PRIORITY(7) }
};
// --------------------------------------------------------------------------
// Private functions
// --------------------------------------------------------------------------
FORCE_INLINE void Disable_Irq(IRQn_Type irq) {
NVIC_DisableIRQ(irq);
// We NEED memory barriers to ensure Interrupts are actually disabled!
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
__DSB();
__ISB();
}
// --------------------------------------------------------------------------
// Public functions
// --------------------------------------------------------------------------
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
Tc * const tc = TimerConfig[timer_num].pTimer;
IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
// Disable interrupt, just in case it was already enabled
Disable_Irq(irq);
// Disable timer interrupt
tc->COUNT32.INTENCLR.reg = TC_INTENCLR_OVF; // disable overflow interrupt
// TCn clock setup
const uint8_t clockID = GCLK_CLKCTRL_IDs[TCC_INST_NUM + timer_num];
GCLK->PCHCTRL[clockID].bit.CHEN = false;
SYNC(GCLK->PCHCTRL[clockID].bit.CHEN);
GCLK->PCHCTRL[clockID].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN; // 120MHz startup code programmed
SYNC(!GCLK->PCHCTRL[clockID].bit.CHEN);
// Stop timer, just in case, to be able to reconfigure it
tc->COUNT32.CTRLA.bit.ENABLE = false;
SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE);
// Reset timer
tc->COUNT32.CTRLA.bit.SWRST = true;
SYNC(tc->COUNT32.SYNCBUSY.bit.SWRST);
NVIC_SetPriority(irq, TimerConfig[timer_num].priority);
// Wave mode, reset counter on overflow on 0 (I use count down to prevent double buffer use)
tc->COUNT32.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ;
tc->COUNT32.CTRLA.reg = TC_CTRLA_MODE_COUNT32 | TC_CTRLA_PRESCALER_DIV1;
tc->COUNT32.CTRLBSET.reg = TC_CTRLBCLR_DIR;
SYNC(tc->COUNT32.SYNCBUSY.bit.CTRLB);
// Set compare value
tc->COUNT32.COUNT.reg = tc->COUNT32.CC[0].reg = HAL_TIMER_RATE / frequency;
// And start timer
tc->COUNT32.CTRLA.bit.ENABLE = true;
SYNC(tc->COUNT32.SYNCBUSY.bit.ENABLE);
// Enable interrupt on RC compare
tc->COUNT32.INTENSET.reg = TC_INTENCLR_OVF; // enable overflow interrupt
// Finally, enable IRQ
NVIC_EnableIRQ(irq);
}
void HAL_timer_enable_interrupt(const uint8_t timer_num) {
IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
NVIC_EnableIRQ(irq);
}
void HAL_timer_disable_interrupt(const uint8_t timer_num) {
IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
Disable_Irq(irq);
}
// missing from CMSIS: Check if interrupt is enabled or not
static bool NVIC_GetEnabledIRQ(IRQn_Type IRQn) {
return (NVIC->ISER[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F))) != 0;
}
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
return NVIC_GetEnabledIRQ(irq);
}
#endif // __SAMD51__

@ -0,0 +1,117 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <stdint.h>
// --------------------------------------------------------------------------
// Defines
// --------------------------------------------------------------------------
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
#define HAL_TIMER_RATE SystemCoreClock // frequency of timers peripherals
#define STEP_TIMER_NUM 0 // index of timer to use for stepper (also +1 for 32bits counter)
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#define TONE_TIMER_NUM 2 // index of timer to use for beeper tones (also +1 for 32bits counter)
#define TEMP_TIMER_NUM 4 // index of timer to use for temperature (also +1 for 32bits counter)
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM)
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM)
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
#define TC_PRIORITY(t) (t == STEP_TIMER_NUM || t == PULSE_TIMER_NUM) ? 2 \
: (t == TEMP_TIMER_NUM) ? 6 \
: (t == TONE_TIMER_NUM) ? 5 : 7
#define _TC_HANDLER(t) void TC##t##_Handler()
#define TC_HANDLER(t) _TC_HANDLER(t)
#define HAL_STEP_TIMER_ISR() TC_HANDLER(STEP_TIMER_NUM)
#if STEP_TIMER_NUM != PULSE_TIMER_NUM
#define HAL_PULSE_TIMER_ISR() TC_HANDLER(PULSE_TIMER_NUM)
#endif
#define HAL_TEMP_TIMER_ISR() TC_HANDLER(TEMP_TIMER_NUM)
#define HAL_TONE_TIMER_ISR() TC_HANDLER(TONE_TIMER_NUM)
// --------------------------------------------------------------------------
// Types
// --------------------------------------------------------------------------
typedef struct {
Tc *pTimer;
IRQn_Type IRQ_Id;
uint8_t priority;
} tTimerConfig;
// --------------------------------------------------------------------------
// Public Variables
// --------------------------------------------------------------------------
extern const tTimerConfig TimerConfig[];
// --------------------------------------------------------------------------
// Public functions
// --------------------------------------------------------------------------
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
Tc * const tc = TimerConfig[timer_num].pTimer;
tc->COUNT32.CC[0].reg = HAL_TIMER_TYPE_MAX - compare;
}
FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
Tc * const tc = TimerConfig[timer_num].pTimer;
return (hal_timer_t)(HAL_TIMER_TYPE_MAX - tc->COUNT32.CC[0].reg);
}
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
Tc * const tc = TimerConfig[timer_num].pTimer;
tc->COUNT32.CTRLBSET.reg = TC_CTRLBCLR_CMD_READSYNC;
SYNC(tc->COUNT32.SYNCBUSY.bit.CTRLB || tc->COUNT32.SYNCBUSY.bit.COUNT);
return HAL_TIMER_TYPE_MAX - tc->COUNT32.COUNT.reg;
}
void HAL_timer_enable_interrupt(const uint8_t timer_num);
void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
Tc * const tc = TimerConfig[timer_num].pTimer;
// Clear interrupt flag
tc->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF;
}
#define HAL_timer_isr_epilogue(timer_num)

@ -0,0 +1,55 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifdef ADAFRUIT_GRAND_CENTRAL_M4
/**
* Framework doesn't define some serial to save sercom resources
* hence if these are used I need to define them
*/
#include "../../inc/MarlinConfig.h"
#if SERIAL_PORT == 1 || SERIAL_PORT_2 == 1
Uart Serial2(&sercom4, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX);
void SERCOM4_0_Handler() { Serial2.IrqHandler(); }
void SERCOM4_1_Handler() { Serial2.IrqHandler(); }
void SERCOM4_2_Handler() { Serial2.IrqHandler(); }
void SERCOM4_3_Handler() { Serial2.IrqHandler(); }
#endif
#if SERIAL_PORT == 2 || SERIAL_PORT_2 == 2
Uart Serial3(&sercom1, PIN_SERIAL3_RX, PIN_SERIAL3_TX, PAD_SERIAL3_RX, PAD_SERIAL3_TX);
void SERCOM1_0_Handler() { Serial3.IrqHandler(); }
void SERCOM1_1_Handler() { Serial3.IrqHandler(); }
void SERCOM1_2_Handler() { Serial3.IrqHandler(); }
void SERCOM1_3_Handler() { Serial3.IrqHandler(); }
#endif
#if SERIAL_PORT == 3 || SERIAL_PORT_2 == 3
Uart Serial4(&sercom5, PIN_SERIAL4_RX, PIN_SERIAL4_TX, PAD_SERIAL4_RX, PAD_SERIAL4_TX);
void SERCOM5_0_Handler() { Serial4.IrqHandler(); }
void SERCOM5_1_Handler() { Serial4.IrqHandler(); }
void SERCOM5_2_Handler() { Serial4.IrqHandler(); }
void SERCOM5_3_Handler() { Serial4.IrqHandler(); }
#endif
#endif // ADAFRUIT_GRAND_CENTRAL_M4

@ -0,0 +1,25 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#pragma once
extern Uart Serial2;
extern Uart Serial3;
extern Uart Serial4;

@ -0,0 +1,70 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#define SYNC(sc) while (sc) { \
asm(""); \
}
// Get SAMD port/pin from specified arduino pin
#define GET_SAMD_PORT(P) _GET_SAMD_PORT(PIN_TO_SAMD_PIN(P))
#define GET_SAMD_PIN(P) _GET_SAMD_PIN(PIN_TO_SAMD_PIN(P))
// Get external interrupt line associated to specified arduino pin
#define PIN_TO_EILINE(P) _SAMDPORTPIN_TO_EILINE(GET_SAMD_PORT(P), GET_SAMD_PIN(P))
// Get adc/ain associated to specified arduino pin
#define PIN_TO_ADC(P) (ANAPIN_TO_ADCAIN(P) >> 8)
#define PIN_TO_AIN(P) (ANAPIN_TO_ADCAIN(P) & 0xFF)
// Private defines
#define PIN_TO_SAMD_PIN(P) DIO##P##_PIN
#define _GET_SAMD_PORT(P) ((P) >> 5)
#define _GET_SAMD_PIN(P) ((P) & 0x1F)
// Get external interrupt line
#define _SAMDPORTPIN_TO_EILINE(P,B) ((P == 0 && WITHIN(B, 0, 31) && B != 8 && B != 26 && B != 28 && B != 29) ? (B) & 0xF \
: (P == 1 && (WITHIN(B, 0, 25) || WITHIN(B, 30, 31))) ? (B) & 0xF \
: (P == 1 && WITHIN(B, 26, 29)) ? 12 + (B) - 26 \
: (P == 2 && (WITHIN(B, 0, 6) || WITHIN(B, 10, 31)) && B != 29) ? (B) & 0xF \
: (P == 2 && B == 7) ? 9 \
: (P == 3 && WITHIN(B, 0, 1)) ? (B) \
: (P == 3 && WITHIN(B, 8, 12)) ? 3 + (B) - 8 \
: (P == 3 && WITHIN(B, 20, 21)) ? 10 + (B) - 20 \
: -1)
// Get adc/ain
#define ANAPIN_TO_ADCAIN(P) _PIN_TO_ADCAIN(ANAPIN_TO_SAMDPIN(P))
#define _PIN_TO_ADCAIN(P) _SAMDPORTPIN_TO_ADCAIN(_GET_SAMD_PORT(P), _GET_SAMD_PIN(P))
#define _SAMDPORTPIN_TO_ADCAIN(P,B) ((P == 0 && WITHIN(B, 2, 3)) ? 0x000 + (B) - 2 \
: (P == 0 && WITHIN(B, 4, 7)) ? 0x000 + (B) \
: (P == 0 && WITHIN(B, 8, 9)) ? 0x100 + 2 + (B) - 8 \
: (P == 0 && WITHIN(B, 10, 11)) ? 0x000 + (B) \
: (P == 1 && WITHIN(B, 0, 3)) ? 0x000 + 12 + (B) \
: (P == 1 && WITHIN(B, 4, 7)) ? 0x100 + 6 + (B) - 4 \
: (P == 1 && WITHIN(B, 8, 9)) ? 0x100 + (B) - 8 \
: (P == 2 && WITHIN(B, 0, 1)) ? 0x100 + 10 + (B) \
: (P == 2 && WITHIN(B, 2, 3)) ? 0x100 + 4 + (B) - 2 \
: (P == 2 && WITHIN(B, 30, 31)) ? 0x100 + 12 + (B) - 30 \
: (P == 3 && WITHIN(B, 0, 1)) ? 0x100 + 14 + (B) \
: -1)

@ -0,0 +1,48 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
/**
* Test SAMD51 specific configuration values for errors at compile-time.
*/
#if defined(ADAFRUIT_GRAND_CENTRAL_M4) && SD_CONNECTION_IS(CUSTOM_CABLE)
#error "No custom SD drive cable defined for this board."
#endif
#if defined(MAX6675_SCK_PIN) && defined(MAX6675_DO_PIN) && (MAX6675_SCK_PIN == SCK1 || MAX6675_DO_PIN == MISO1)
#error "OnBoard SPI BUS can't be shared with other devices."
#endif
#if ENABLED(EMERGENCY_PARSER)
#error "EMERGENCY_PARSER is not yet implemented for STM32F4. Disable EMERGENCY_PARSER to continue."
#endif
#if ENABLED(SDIO_SUPPORT)
#error "SDIO_SUPPORT is not supported."
#endif
#if ENABLED(FAST_PWM_FAN)
#error "FAST_PWM_FAN is not yet implemented for this platform."
#endif
#if ENABLED(EEPROM_SETTINGS) && NONE(SPI_EEPROM, I2C_EEPROM)
#warning "Did you activate the SmartEEPROM? See https://github.com/GMagician/SAMD51-SmartEEprom-Activator"
#endif

@ -0,0 +1,59 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
/**
* Description: Tone function for Arduino Due and compatible (SAM3X8E)
* Derived from http://forum.arduino.cc/index.php?topic=136500.msg2903012#msg2903012
*/
#ifdef __SAMD51__
#include "../../inc/MarlinConfig.h"
#include "HAL_timers_SAMD51.h"
static pin_t tone_pin;
volatile static int32_t toggles;
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration) {
tone_pin = _pin;
toggles = 2 * frequency * duration / 1000;
HAL_timer_start(TONE_TIMER_NUM, 2 * frequency);
}
void noTone(const pin_t _pin) {
HAL_timer_disable_interrupt(TONE_TIMER_NUM);
extDigitalWrite(_pin, LOW);
}
HAL_TONE_TIMER_ISR() {
static bool pin_state = false;
HAL_timer_isr_prologue(TONE_TIMER_NUM);
if (toggles) {
toggles--;
extDigitalWrite(tone_pin, (pin_state = !pin_state));
}
else noTone(tone_pin); // turn off interrupt
HAL_timer_isr_epilogue(TONE_TIMER_NUM);
}
#endif // __SAMD51__

@ -0,0 +1,184 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#pragma once
/**
* Endstop interrupts for ATMEL SAMD51 based targets.
*
* On SAMD51, all pins support external interrupt capability.
* Any pin can be used for external interrupts, but there are some restrictions.
* At most 16 different external interrupts can be used at one time.
* Further, you cant just pick any 16 pins to use. This is because every pin on the SAMD51
* connects to what is called an EXTINT line, and only one pin per EXTINT line can be used for external
* interrupts at a time
*/
/**
* Endstop Interrupts
*
* Without endstop interrupts the endstop pins must be polled continually in
* the temperature-ISR via endstops.update(), most of the time finding no change.
* With this feature endstops.update() is called only when we know that at
* least one endstop has changed state, saving valuable CPU cycles.
*
* This feature only works when all used endstop pins can generate an 'external interrupt'.
*
* Test whether pins issue interrupts on your board by flashing 'pin_interrupt_test.ino'.
* (Located in Marlin/buildroot/share/pin_interrupt_test/pin_interrupt_test.ino)
*/
#include "../../module/endstops.h"
#define MATCH_EILINE(P1,P2) (P1 != P2 && PIN_TO_EILINE(P1) == PIN_TO_EILINE(P2))
#if HAS_X_MAX
#define MATCH_X_MAX_EILINE(P) MATCH_EILINE(P, X_MAX_PIN)
#else
#define MATCH_X_MAX_EILINE(P) false
#endif
#if HAS_X_MIN
#define MATCH_X_MIN_EILINE(P) MATCH_EILINE(P, X_MIN_PIN)
#else
#define MATCH_X_MIN_EILINE(P) false
#endif
#if HAS_Y_MAX
#define MATCH_Y_MAX_EILINE(P) MATCH_EILINE(P, Y_MAX_PIN)
#else
#define MATCH_Y_MAX_EILINE(P) false
#endif
#if HAS_Y_MIN
#define MATCH_Y_MIN_EILINE(P) MATCH_EILINE(P, Y_MIN_PIN)
#else
#define MATCH_Y_MIN_EILINE(P) false
#endif
#if HAS_Z_MAX
#define MATCH_Z_MAX_EILINE(P) MATCH_EILINE(P, Z_MAX_PIN)
#else
#define MATCH_Z_MAX_EILINE(P) false
#endif
#if HAS_Z_MIN
#define MATCH_Z_MIN_EILINE(P) MATCH_EILINE(P, Z_MIN_PIN)
#else
#define MATCH_Z_MIN_EILINE(P) false
#endif
#if HAS_Z2_MAX
#define MATCH_Z2_MAX_EILINE(P) MATCH_EILINE(P, Z2_MAX_PIN)
#else
#define MATCH_Z2_MAX_EILINE(P) false
#endif
#if HAS_Z2_MIN
#define MATCH_Z2_MIN_EILINE(P) MATCH_EILINE(P, Z2_MIN_PIN)
#else
#define MATCH_Z2_MIN_EILINE(P) false
#endif
#if HAS_Z3_MAX
#define MATCH_Z3_MAX_EILINE(P) MATCH_EILINE(P, Z3_MAX_PIN)
#else
#define MATCH_Z3_MAX_EILINE(P) false
#endif
#if HAS_Z3_MIN
#define MATCH_Z3_MIN_EILINE(P) MATCH_EILINE(P, Z3_MIN_PIN)
#else
#define MATCH_Z3_MIN_EILINE(P) false
#endif
#if HAS_Z_MIN_PROBE_PIN
#define MATCH_Z_MIN_PROBE_EILINE(P) MATCH_EILINE(P, Z_MIN_PROBE_PIN)
#else
#define MATCH_Z_MIN_PROBE_EILINE(P) false
#endif
#define AVAILABLE_EILINE(P) (PIN_TO_EILINE(P) != -1 \
&& !MATCH_X_MAX_EILINE(P) && !MATCH_X_MIN_EILINE(P) \
&& !MATCH_Y_MAX_EILINE(P) && !MATCH_Y_MIN_EILINE(P) \
&& !MATCH_Z_MAX_EILINE(P) && !MATCH_Z_MIN_EILINE(P) \
&& !MATCH_Z2_MAX_EILINE(P) && !MATCH_Z2_MIN_EILINE(P) \
&& !MATCH_Z3_MAX_EILINE(P) && !MATCH_Z3_MIN_EILINE(P) \
&& !MATCH_Z_MIN_PROBE_EILINE(P))
// One ISR for all EXT-Interrupts
void endstop_ISR(void) { endstops.update(); }
void setup_endstop_interrupts(void) {
#if HAS_X_MAX
#if !AVAILABLE_EILINE(X_MAX_PIN)
static_assert(false, "X_MAX_PIN has no EXTINT line available.");
#endif
attachInterrupt(X_MAX_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_X_MIN
#if !AVAILABLE_EILINE(X_MIN_PIN)
static_assert(false, "X_MIN_PIN has no EXTINT line available.");
#endif
attachInterrupt(X_MIN_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_Y_MAX
#if !AVAILABLE_EILINE(Y_MAX_PIN)
static_assert(false, "Y_MAX_PIN has no EXTINT line available.");
#endif
attachInterrupt(Y_MAX_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_Y_MIN
#if !AVAILABLE_EILINE(Y_MIN_PIN)
static_assert(false, "Y_MIN_PIN has no EXTINT line available.");
#endif
attachInterrupt(Y_MIN_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_Z_MAX
#if !AVAILABLE_EILINE(Z_MAX_PIN)
static_assert(false, "Z_MAX_PIN has no EXTINT line available.");
#endif
attachInterrupt(Z_MAX_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_Z_MIN
#if !AVAILABLE_EILINE(Z_MIN_PIN)
static_assert(false, "Z_MIN_PIN has no EXTINT line available.");
#endif
attachInterrupt(Z_MIN_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_Z2_MAX
#if !AVAILABLE_EILINE(Z2_MAX_PIN)
static_assert(false, "Z2_MAX_PIN has no EXTINT line available.");
#endif
attachInterrupt(Z2_MAX_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_Z2_MIN
#if !AVAILABLE_EILINE(Z2_MIN_PIN)
static_assert(false, "Z2_MIN_PIN has no EXTINT line available.");
#endif
attachInterrupt(Z2_MIN_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_Z3_MAX
#if !AVAILABLE_EILINE(Z3_MAX_PIN)
static_assert(false, "Z3_MAX_PIN has no EXTINT line available.");
#endif
attachInterrupt(Z3_MAX_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_Z3_MIN
#if !AVAILABLE_EILINE(Z3_MIN_PIN)
static_assert(false, "Z3_MIN_PIN has no EXTINT line available.");
#endif
attachInterrupt(Z3_MIN_PIN, endstop_ISR, CHANGE);
#endif
#if HAS_Z_MIN_PROBE_PIN
#if !AVAILABLE_EILINE(Z_MIN_PROBE_PIN)
static_assert(false, "Z_MIN_PROBE_PIN has no EXTINT line available.");
#endif
attachInterrupt(Z_MIN_PROBE_PIN, endstop_ISR, CHANGE);
#endif
}

@ -0,0 +1,251 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#pragma once
/**
* Fast IO functions for SAMD51
*/
#include "SAMD51.h"
/**
* Utility functions
*/
#ifndef MASK
#define MASK(PIN) (1 << PIN)
#endif
/**
* Magic I/O routines
*
* Now you can simply SET_OUTPUT(STEP); WRITE(STEP, HIGH); WRITE(STEP, LOW);
*/
// Read a pin
#define READ(IO) ((PORT->Group[(EPortType)GET_SAMD_PORT(IO)].IN.reg & MASK(GET_SAMD_PIN(IO))) != 0)
// Write to a pin
#define WRITE(IO,V) do{ \
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
const uint32_t mask = MASK(GET_SAMD_PIN(IO)); \
\
if (V) PORT->Group[port].OUTSET.reg = mask; \
else PORT->Group[port].OUTCLR.reg = mask; \
}while(0)
// Toggle a pin
#define TOGGLE(IO) PORT->Group[(EPortType)GET_SAMD_PORT(IO)].OUTTGL.reg = MASK(GET_SAMD_PIN(IO));
// Set pin as input
#define SET_INPUT(IO) do{ \
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
const uint32_t pin = GET_SAMD_PIN(IO); \
\
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_INEN); \
PORT->Group[port].DIRCLR.reg = MASK(pin); \
}while(0)
// Set pin as input with pullup
#define SET_INPUT_PULLUP(IO) do{ \
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
const uint32_t pin = GET_SAMD_PIN(IO); \
const uint32_t mask = MASK(pin); \
\
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_INEN | PORT_PINCFG_PULLEN); \
PORT->Group[port].DIRCLR.reg = mask; \
PORT->Group[port].OUTSET.reg = mask; \
}while(0)
// Set pin as input with pulldown
#define SET_INPUT_PULLDOWN(IO) do{ \
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
const uint32_t pin = GET_SAMD_PIN(IO); \
const uint32_t mask = MASK(pin); \
\
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_INEN | PORT_PINCFG_PULLEN); \
PORT->Group[port].DIRCLR.reg = mask; \
PORT->Group[port].OUTCLR.reg = mask; \
}while(0)
// Set pin as output (push pull)
#define SET_OUTPUT(IO) do{ \
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
const uint32_t pin = GET_SAMD_PIN(IO); \
\
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_INEN); \
PORT->Group[port].DIRSET.reg = MASK(pin); \
}while(0)
// Set pin as output (open drain)
#define SET_OUTPUT_OD(IO) do{ \
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
const uint32_t pin = GET_SAMD_PIN(IO); \
\
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_PULLEN); \
PORT->Group[port].DIRCLR.reg = MASK(pin); \
}while(0)
// Set pin as PWM (push pull)
#define SET_PWM(IO) SET_OUTPUT(IO)
// Set pin as PWM (open drain)
#define SET_PWM_OD(IO) SET_OUTPUT_OD(IO)
// check if pin is an output
#define IS_OUTPUT(IO) ((PORT->Group[(EPortType)GET_SAMD_PORT(IO)].DIR.reg & MASK(GET_SAMD_PIN(IO))) \
|| (PORT->Group[(EPortType)GET_SAMD_PORT(IO)].PINCFG[GET_SAMD_PIN(IO)].reg & (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN)) == PORT_PINCFG_PULLEN)
// check if pin is an input
#define IS_INPUT(IO) !IS_OUTPUT(IO)
// Shorthand
#define OUT_WRITE(IO,V) do{ SET_OUTPUT(IO); WRITE(IO,V); }while(0)
#define OUT_WRITE_OD(IO,V) do{ SET_OUTPUT_OD(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!
*/
#ifdef ADAFRUIT_GRAND_CENTRAL_M4
/*
* Adafruit Grand Central M4 has a lot of PWMs the availables are listed here.
* Some of these share the same source and so can't be used in the same time
*/
#define PWM_PIN(P) (WITHIN(P, 2, 13) || WITHIN(P, 22, 23) || WITHIN(P, 44, 45) || P == 48)
// Return fullfilled ADCx->INPUTCTRL.reg
#define PIN_TO_INPUTCTRL(P) ( (PIN_TO_AIN(P) == 0) ? ADC_INPUTCTRL_MUXPOS_AIN0 \
: (PIN_TO_AIN(P) == 1) ? ADC_INPUTCTRL_MUXPOS_AIN1 \
: (PIN_TO_AIN(P) == 2) ? ADC_INPUTCTRL_MUXPOS_AIN2 \
: (PIN_TO_AIN(P) == 3) ? ADC_INPUTCTRL_MUXPOS_AIN3 \
: (PIN_TO_AIN(P) == 4) ? ADC_INPUTCTRL_MUXPOS_AIN4 \
: (PIN_TO_AIN(P) == 5) ? ADC_INPUTCTRL_MUXPOS_AIN5 \
: (PIN_TO_AIN(P) == 6) ? ADC_INPUTCTRL_MUXPOS_AIN6 \
: (PIN_TO_AIN(P) == 7) ? ADC_INPUTCTRL_MUXPOS_AIN7 \
: (PIN_TO_AIN(P) == 8) ? ADC_INPUTCTRL_MUXPOS_AIN8 \
: (PIN_TO_AIN(P) == 9) ? ADC_INPUTCTRL_MUXPOS_AIN9 \
: (PIN_TO_AIN(P) == 10) ? ADC_INPUTCTRL_MUXPOS_AIN10 \
: (PIN_TO_AIN(P) == 11) ? ADC_INPUTCTRL_MUXPOS_AIN11 \
: (PIN_TO_AIN(P) == 12) ? ADC_INPUTCTRL_MUXPOS_AIN12 \
: (PIN_TO_AIN(P) == 13) ? ADC_INPUTCTRL_MUXPOS_AIN13 \
: (PIN_TO_AIN(P) == 14) ? ADC_INPUTCTRL_MUXPOS_AIN14 \
: ADC_INPUTCTRL_MUXPOS_AIN15)
#define ANAPIN_TO_SAMDPIN(P) ( (P == 0) ? PIN_TO_SAMD_PIN(67) \
: (P == 1) ? PIN_TO_SAMD_PIN(68) \
: (P == 2) ? PIN_TO_SAMD_PIN(69) \
: (P == 3) ? PIN_TO_SAMD_PIN(70) \
: (P == 4) ? PIN_TO_SAMD_PIN(71) \
: (P == 5) ? PIN_TO_SAMD_PIN(72) \
: (P == 6) ? PIN_TO_SAMD_PIN(73) \
: (P == 7) ? PIN_TO_SAMD_PIN(74) \
: (P == 8) ? PIN_TO_SAMD_PIN(54) \
: (P == 9) ? PIN_TO_SAMD_PIN(55) \
: (P == 10) ? PIN_TO_SAMD_PIN(56) \
: (P == 11) ? PIN_TO_SAMD_PIN(57) \
: (P == 12) ? PIN_TO_SAMD_PIN(58) \
: (P == 13) ? PIN_TO_SAMD_PIN(59) \
: (P == 14) ? PIN_TO_SAMD_PIN(60) \
: (P == 15) ? PIN_TO_SAMD_PIN(61) \
: (P == 16) ? PIN_TO_SAMD_PIN(12) \
: (P == 17) ? PIN_TO_SAMD_PIN(13) \
: PIN_TO_SAMD_PIN(9))
#define digitalPinToAnalogInput(P) (WITHIN(P, 67, 74) ? (P) - 67 : WITHIN(P, 54, 61) ? 8 + (P) - 54 : WITHIN(P, 12, 13) ? 16 + (P) - 12 : P == 9 ? 18 : -1)
/*
* pins
*/
// PORTA
#define DIO67_PIN PIN_PA02 // A0
#define DIO59_PIN PIN_PA04 // A13
#define DIO68_PIN PIN_PA05 // A1
#define DIO60_PIN PIN_PA06 // A14
#define DIO61_PIN PIN_PA07 // A15
#define DIO26_PIN PIN_PA12
#define DIO27_PIN PIN_PA13
#define DIO28_PIN PIN_PA14
#define DIO23_PIN PIN_PA15
#define DIO37_PIN PIN_PA16
#define DIO36_PIN PIN_PA17
#define DIO35_PIN PIN_PA18
#define DIO34_PIN PIN_PA19
#define DIO33_PIN PIN_PA20
#define DIO32_PIN PIN_PA21
#define DIO31_PIN PIN_PA22
#define DIO30_PIN PIN_PA23
// PORTB
#define DIO12_PIN PIN_PB00 // A16
#define DIO13_PIN PIN_PB01 // A17
#define DIO9_PIN PIN_PB02 // A18
#define DIO69_PIN PIN_PB03 // A2
#define DIO74_PIN PIN_PB04 // A7
#define DIO54_PIN PIN_PB05 // A8
#define DIO55_PIN PIN_PB06 // A9
#define DIO56_PIN PIN_PB07 // A10
#define DIO57_PIN PIN_PB08 // A11
#define DIO58_PIN PIN_PB09 // A12
#define DIO18_PIN PIN_PB12
#define DIO19_PIN PIN_PB13
#define DIO39_PIN PIN_PB14
#define DIO38_PIN PIN_PB15
#define DIO14_PIN PIN_PB16
#define DIO15_PIN PIN_PB17
#define DIO8_PIN PIN_PB18
#define DIO29_PIN PIN_PB19
#define DIO20_PIN PIN_PB20
#define DIO21_PIN PIN_PB21
#define DIO10_PIN PIN_PB22
#define DIO11_PIN PIN_PB23
#define DIO1_PIN PIN_PB24
#define DIO0_PIN PIN_PB25
#define DIO83_PIN PIN_PB28 // SD_CS
#define DIO95_PIN PIN_PB31 // SD_CD
// PORTC
#define DIO70_PIN PIN_PC00 // A3
#define DIO71_PIN PIN_PC01 // A4
#define DIO72_PIN PIN_PC02 // A5
#define DIO73_PIN PIN_PC03 // A6
#define DIO48_PIN PIN_PC04
#define DIO49_PIN PIN_PC05
#define DIO46_PIN PIN_PC06
#define DIO47_PIN PIN_PC07
#define DIO45_PIN PIN_PC10
#define DIO44_PIN PIN_PC11
#define DIO41_PIN PIN_PC12
#define DIO40_PIN PIN_PC13
#define DIO43_PIN PIN_PC14
#define DIO42_PIN PIN_PC15
#define DIO25_PIN PIN_PC16
#define DIO24_PIN PIN_PC17
#define DIO2_PIN PIN_PC18
#define DIO3_PIN PIN_PC19
#define DIO4_PIN PIN_PC20
#define DIO5_PIN PIN_PC21
#define DIO16_PIN PIN_PC22
#define DIO17_PIN PIN_PC23
// PORTD
#define DIO22_PIN PIN_PD12
#define DIO6_PIN PIN_PD20
#define DIO7_PIN PIN_PD21
#endif // ADAFRUIT_GRAND_CENTRAL_M4

@ -0,0 +1,129 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifdef __SAMD51__
#include "../../inc/MarlinConfig.h"
#if ENABLED(EEPROM_SETTINGS)
#include "../shared/persistent_store_api.h"
#if NONE(SPI_EEPROM, I2C_EEPROM)
#define NVMCTRL_CMD(c) do{ \
SYNC(!NVMCTRL->STATUS.bit.READY); \
NVMCTRL->INTFLAG.bit.DONE = true; \
NVMCTRL->CTRLB.reg = c | NVMCTRL_CTRLB_CMDEX_KEY; \
SYNC(NVMCTRL->INTFLAG.bit.DONE); \
}while(0)
#define NVMCTRL_FLUSH() do{ \
if (NVMCTRL->SEESTAT.bit.LOAD) \
NVMCTRL_CMD(NVMCTRL_CTRLB_CMD_SEEFLUSH); \
}while(0)
#endif
bool PersistentStore::access_start() {
#if NONE(SPI_EEPROM, I2C_EEPROM)
NVMCTRL->SEECFG.reg = NVMCTRL_SEECFG_WMODE_BUFFERED; // Buffered mode and segment reallocation active
#endif
return true;
}
bool PersistentStore::access_finish() {
#if NONE(SPI_EEPROM, I2C_EEPROM)
NVMCTRL_FLUSH();
if (!NVMCTRL->SEESTAT.bit.LOCK)
NVMCTRL_CMD(NVMCTRL_CTRLB_CMD_LSEE); // Lock E2P data write access
#endif
return true;
}
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
#if NONE(SPI_EEPROM, I2C_EEPROM)
if (NVMCTRL->SEESTAT.bit.RLOCK)
NVMCTRL_CMD(NVMCTRL_CTRLB_CMD_USEE); // Unlock E2P data write access
#endif
while (size--) {
const uint8_t v = *value;
#if ANY(SPI_EEPROM, I2C_EEPROM)
uint8_t * const p = (uint8_t * const)pos;
if (v != eeprom_read_byte(p)) {
eeprom_write_byte(p, v);
delay(2);
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(MSG_ERR_EEPROM_WRITE);
return true;
}
}
#else
SYNC(NVMCTRL->SEESTAT.bit.BUSY);
if (NVMCTRL->INTFLAG.bit.SEESFULL)
NVMCTRL_FLUSH(); // Next write will trigger a sector reallocation. I need to flush 'pagebuffer'
((volatile uint8_t *)SEEPROM_ADDR)[pos] = v;
SYNC(!NVMCTRL->INTFLAG.bit.SEEWRC);
#endif
crc16(crc, &v, 1);
pos++;
value++;
}
return false;
}
bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
while (size--) {
uint8_t c;
#if ANY(SPI_EEPROM, I2C_EEPROM)
c = eeprom_read_byte((uint8_t*)pos);
#else
SYNC(NVMCTRL->SEESTAT.bit.BUSY);
c = ((volatile uint8_t *)SEEPROM_ADDR)[pos];
#endif
if (writing) *value = c;
crc16(crc, &c, 1);
pos++;
value++;
}
return false;
}
size_t PersistentStore::capacity() {
#if ANY(SPI_EEPROM, I2C_EEPROM)
return E2END + 1;
#else
const uint8_t psz = NVMCTRL->SEESTAT.bit.PSZ,
sblk = NVMCTRL->SEESTAT.bit.SBLK;
if (!psz && !sblk) return 0;
else if (psz <= 2) return (0x200 << psz);
else if (sblk == 1 || psz == 3) return 4096;
else if (sblk == 2 || psz == 4) return 8192;
else if (sblk <= 4 || psz == 5) return 16384;
else if (sblk >= 9 && psz == 7) return 65536;
else return 32768;
#endif
}
#endif // EEPROM_SETTINGS
#endif // __SAMD51__

@ -0,0 +1,153 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#define NUMBER_PINS_TOTAL PINS_COUNT
#define digitalRead_mod(p) extDigitalRead(p)
#define PRINT_PORT(p) do{ SERIAL_ECHOPGM(" Port: "); sprintf_P(buffer, PSTR("%c%02ld"), 'A' + g_APinDescription[p].ulPort, g_APinDescription[p].ulPin); SERIAL_ECHO(buffer); }while (0)
#define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0)
#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%3d "), p); SERIAL_ECHO(buffer); }while(0)
#define GET_ARRAY_PIN(p) pin_array[p].pin
#define GET_ARRAY_IS_DIGITAL(p) pin_array[p].is_digital
#define VALID_PIN(pin) (pin >= 0 && pin < (int8_t)NUMBER_PINS_TOTAL)
#define DIGITAL_PIN_TO_ANALOG_PIN(p) digitalPinToAnalogInput(p)
#define IS_ANALOG(P) (DIGITAL_PIN_TO_ANALOG_PIN(P)!=-1)
#define pwm_status(pin) digitalPinHasPWM(pin)
#define MULTI_NAME_PAD 27 // space needed to be pretty if not first name assigned to a pin
// pins that will cause hang/reset/disconnect in M43 Toggle and Watch utilities
// uses pin index
#define M43_NEVER_TOUCH(Q) ((Q) >= 75)
bool GET_PINMODE(int8_t pin) { // 1: output, 0: input
const EPortType samdport = g_APinDescription[pin].ulPort;
const uint32_t samdpin = g_APinDescription[pin].ulPin;
return PORT->Group[samdport].DIR.reg & MASK(samdpin) || (PORT->Group[samdport].PINCFG[samdpin].reg & (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN)) == PORT_PINCFG_PULLEN;
}
void pwm_details(int32_t pin) {
if (pwm_status(pin)) {
//uint32_t chan = g_APinDescription[pin].ulPWMChannel TODO when fast pwm is operative;
//SERIAL_ECHOPAIR("PWM = ", duty);
}
}
/**
* AGCM4 Board pin | PORT | Label
* ----------------+--------+-------
* 0 | PB25 | "RX0"
* 1 | PB24 | "TX0"
* 2 | PC18 |
* 3 | PC19 |
* 4 | PC20 |
* 5 | PC21 |
* 6 | PD20 |
* 7 | PD21 |
* 8 | PB18 |
* 9 | PB2 |
* 10 | PB22 |
* 11 | PB23 |
* 12 | PB0 | "A16"
* 13 | PB1 | LED AMBER "L" / "A17"
* 14 | PB16 | "TX3"
* 15 | PB17 | "RX3"
* 16 | PC22 | "TX2"
* 17 | PC23 | "RX2"
* 18 | PB12 | "TX1" / "A18"
* 19 | PB13 | "RX1"
* 20 | PB20 | "SDA"
* 21 | PB21 | "SCL"
* 22 | PD12 |
* 23 | PA15 |
* 24 | PC17 |
* 25 | PC16 |
* 26 | PA12 |
* 27 | PA13 |
* 28 | PA14 |
* 29 | PB19 |
* 30 | PA23 |
* 31 | PA22 |
* 32 | PA21 |
* 33 | PA20 |
* 34 | PA19 |
* 35 | PA18 |
* 36 | PA17 |
* 37 | PA16 |
* 38 | PB15 |
* 39 | PB14 |
* 40 | PC13 |
* 41 | PC12 |
* 42 | PC15 |
* 43 | PC14 |
* 44 | PC11 |
* 45 | PC10 |
* 46 | PC6 |
* 47 | PC7 |
* 48 | PC4 |
* 49 | PC5 |
* 50 | PD11 |
* 51 | PD8 |
* 52 | PD9 |
* 53 | PD10 |
* 54 | PB5 | "A8"
* 55 | PB6 | "A9"
* 56 | PB7 | "A10"
* 57 | PB8 | "A11"
* 58 | PB9 | "A12"
* 69 | PA4 | "A13"
* 60 | PA6 | "A14"
* 61 | PA7 | "A15"
* 62 | PB17 |
* 63 | PB20 |
* 64 | PD11 |
* 65 | PD8 |
* 66 | PD9 |
* 67 | PA2 | "A0" / "DAC0"
* 68 | PA5 | "A1" / "DAC1"
* 69 | PB3 | "A2"
* 70 | PC0 | "A3"
* 71 | PC1 | "A4"
* 72 | PC2 | "A5"
* 73 | PC3 | "A6"
* 74 | PB4 | "A7"
* 75 | PC31 | LED GREEN "RX"
* 76 | PC30 | LED GREEN "TX"
* 77 | PA27 | USB: Host enable
* 78 | PA24 | USB: D-
* 79 | PA25 | USB: D+
* 80 | PB29 | SD: MISO
* 81 | PB27 | SD: SCK
* 82 | PB26 | SD: MOSI
* 83 | PB28 | SD: CS
* 84 | PA3 | AREF
* 85 | PA2 | DAC0 (Duplicate)
* 86 | PA5 | DAC1 (Duplicate)
* 87 | PB1 | LED AMBER "L" (Duplicate)
* 88 | PC24 | NeoPixel
* 89 | PB10 | QSPI: SCK
* 90 | PB11 | QSPI: CS
* 91 | PA8 | QSPI: IO0
* 92 | PA9 | QSPI: IO1
* 93 | PA10 | QSPI: IO2
* 94 | PA11 | QSPI: IO3
*
*/

@ -0,0 +1,54 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#ifdef ADAFRUIT_GRAND_CENTRAL_M4
/*
* AGCM4 Default SPI Pins
*
* SS SCK MISO MOSI
* +-------------------------+
* SPI | 53 52 50 51 |
* SPI1 | 83 81 80 82 |
* +-------------------------+
* Any pin can be used for Chip Select (SS_PIN)
*/
#ifndef SCK_PIN
#define SCK_PIN 52
#endif
#ifndef MISO_PIN
#define MISO_PIN 50
#endif
#ifndef MOSI_PIN
#define MOSI_PIN 51
#endif
#ifndef SDSS
#define SDSS 53
#endif
#else
#error "Unsupported board!"
#endif
#define SS_PIN SDSS

@ -0,0 +1,53 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifdef __SAMD51__
#include "../../inc/MarlinConfig.h"
#if ENABLED(USE_WATCHDOG)
#include "watchdog_SAMD51.h"
void watchdog_init(void) {
// The low-power oscillator used by the WDT runs at 32,768 Hz with
// a 1:32 prescale, thus 1024 Hz, though probably not super precise.
// Setup WDT clocks
MCLK->APBAMASK.bit.OSC32KCTRL_ = true;
MCLK->APBAMASK.bit.WDT_ = true;
OSC32KCTRL->OSCULP32K.bit.EN1K = true; // Enable out 1K (this is what WDT uses)
WDT->CTRLA.bit.ENABLE = false; // Disable watchdog for config
SYNC(WDT->SYNCBUSY.bit.ENABLE);
WDT->INTENCLR.reg = WDT_INTENCLR_EW; // Disable early warning interrupt
WDT->CONFIG.reg = WDT_CONFIG_PER_CYC4096; // Set at least 4s period for chip reset
watchdog_reset();
WDT->CTRLA.reg = WDT_CTRLA_ENABLE; // Start watchdog now in normal mode
SYNC(WDT->SYNCBUSY.bit.ENABLE);
}
#endif // USE_WATCHDOG
#endif // __SAMD51__

@ -0,0 +1,31 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#pragma once
// Initialize watchdog with a 4 second interrupt time
void watchdog_init();
// Reset watchdog. MUST be called at least every 4 seconds after the
// first watchdog_init or SAMD will go into emergency procedures.
inline void watchdog_reset() {
SYNC(WDT->SYNCBUSY.bit.CLEAR); // Test first if previous is 'ongoing' to save time waiting for command execution
WDT->CLEAR.reg = WDT_CLEAR_CLEAR_KEY;
}

@ -129,6 +129,17 @@
#define END_FLASH_ADDR 0x00140000
#endif
#ifdef __SAMD51P20A__
// For SAMD51x20, valid address ranges are
// SRAM (0x20000000 - 0x20040000) (256kb)
// FLASH (0x00000000 - 0x00100000) (1024kb)
//
#define START_SRAM_ADDR 0x20000000
#define END_SRAM_ADDR 0x20040000
#define START_FLASH_ADDR 0x00000000
#define END_FLASH_ADDR 0x00100000
#endif
static bool validate_addr(uint32_t addr) {
// Address must be in SRAM range

@ -302,6 +302,11 @@
//
#define BOARD_ESP32 6000
//
// SAMD51 ARM Cortex M4
//
#define BOARD_AGCM4_RURAMPS4D_13 6100
//
// Simulations
//

@ -120,7 +120,7 @@
|| AXIS_DRIVER_TYPE(A,TMC5160) )
//
// Stretching 'drivers.h' to include LPC SD options
// Stretching 'drivers.h' to include LPC/SAMD51 SD options
//
#define _SDCARD_LCD 1
#define _SDCARD_ONBOARD 2

@ -75,7 +75,7 @@
char *end_bss = &__bss_end__,
*stacklimit = &__StackLimit,
*heaplimit = &__HeapLimit ;
*heaplimit = &__HeapLimit;
#define MEMORY_END_CORRECTION 0x200
@ -94,6 +94,20 @@
#define MEMORY_END_CORRECTION 0x10000 // need to stay well below 0x20080000 or M100 F crashes
#elif defined(__SAMD51__)
extern unsigned int __bss_end__, __StackLimit, __HeapLimit;
extern "C" void * _sbrk(int incr);
void *end_bss = &__bss_end__,
*stacklimit = &__StackLimit,
*heaplimit = &__HeapLimit;
#define MEMORY_END_CORRECTION 0x400
char *free_memory_start = (char *)_sbrk(0) + 0x200, // Leave some heap space
*free_memory_end = (char *)stacklimit - MEMORY_END_CORRECTION;
#else
#error "M100 - unsupported CPU"
#endif

@ -605,3 +605,5 @@
#endif
#define IS_RE_ARM_BOARD (MB(RAMPS_14_RE_ARM_EFB) || MB(RAMPS_14_RE_ARM_EEB) || MB(RAMPS_14_RE_ARM_EFF) || MB(RAMPS_14_RE_ARM_EEF) || MB(RAMPS_14_RE_ARM_SF))
#define HAS_SDCARD_CONNECTION EITHER(TARGET_LPC1768, ADAFRUIT_GRAND_CENTRAL_M4)

@ -515,6 +515,13 @@
#elif MB(ESP32)
#include "esp32/pins_ESP32.h" // ESP32 env:esp32
//
// Adafruit Grand Central M4 (SAMD51 ARM Cortex-M4)
//
#elif MB(AGCM4_RURAMPS4D_13)
#include "samd/pins_AGCM4_RURAMPS4D_13.h" // SAMD51 env:adafruit_grandcentral_m4
//
// Linux Native Debug board
//

@ -51,7 +51,7 @@
#if PIN_EXISTS(MAIN_VOLTAGE_MEASURE) && MAIN_VOLTAGE_MEASURE_PIN < NUM_ANALOG_INPUTS
REPORT_NAME_ANALOG(__LINE__, MAIN_VOLTAGE_MEASURE_PIN)
#endif
#if !defined(ARDUINO_ARCH_SAM) //TC1 & TC2 are macros in the SAM tool chain
#if !defined(ARDUINO_ARCH_SAM) && !defined(ARDUINO_ARCH_SAMD) //TC1 & TC2 are macros in the SAM/SAMD tool chain
#if defined(TC1) && TC1 >= 0 && TC1 < NUM_ANALOG_INPUTS
REPORT_NAME_ANALOG(__LINE__, TC1)
#endif

@ -0,0 +1,254 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2019 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 <http://www.gnu.org/licenses/>.
*/
/**
* Adafruit Grand Central M4 pin assignments ported by Giuliano Zaro
*/
#ifndef ARDUINO_GRAND_CENTRAL_M4
#error "Oops! Select 'Adafruit Grand Central M4' in 'Tools > Board.'"
#endif
#define BOARD_NAME "RuRAMPS4AGCM4 v1.3"
//
// Servos
//
#define SERVO0_PIN 5
#define SERVO1_PIN 3
//
// Limit Switches
//
#define X_MIN_PIN 45
#define X_MAX_PIN 39
#define Y_MIN_PIN 46
#define Y_MAX_PIN 41
#define Z_MIN_PIN 47
#define Z_MAX_PIN 43
//
// Z Probe (when not Z_MIN_PIN)
//
#ifndef Z_MIN_PROBE_PIN
#define Z_MIN_PROBE_PIN 49
#endif
//
// Steppers
//
#define X_STEP_PIN 37 // Support Extension Board
#define X_DIR_PIN 36
#define X_ENABLE_PIN 31
#ifndef X_CS_PIN
#define X_CS_PIN 38
#endif
#define Y_STEP_PIN 32 // Support Extension Board
#define Y_DIR_PIN 35
#define Y_ENABLE_PIN 31
#ifndef Y_CS_PIN
#define Y_CS_PIN 34
#endif
#define Z_STEP_PIN 30 // Support Extension Board
#define Z_DIR_PIN 2
#define Z_ENABLE_PIN 31
#ifndef Z_CS_PIN
#define Z_CS_PIN 10
#endif
#define E0_STEP_PIN 29
#define E0_DIR_PIN 28
#define E0_ENABLE_PIN 33
#ifndef E0_CS_PIN
#define E0_CS_PIN 14
#endif
#define E1_STEP_PIN 22
#define E1_DIR_PIN 24
#define E1_ENABLE_PIN 26
#ifndef E1_CS_PIN
#define E1_CS_PIN 15
#endif
#define E2_STEP_PIN 25
#define E2_DIR_PIN 23
#define E2_ENABLE_PIN 27
#ifndef E2_CS_PIN
#define E2_CS_PIN 74
#endif
#if USES_Z_MIN_PROBE_ENDSTOP
#define Z_MIN_PROBE_PIN 49
#endif
#if HAS_FILAMENT_SENSOR
#ifndef FIL_RUNOUT_PIN
#define FIL_RUNOUT_PIN Y_MIN_PIN
#endif
#endif
//
// Heaters / Fans
//
#define HEATER_0_PIN 13
#define HEATER_1_PIN 12
#define HEATER_2_PIN 11
#define HEATER_BED_PIN 7 // BED H1
#define FAN_PIN 9
#define FAN1_PIN 8
#define CONTROLLER_FAN_PIN -1
//
// Temperature Sensors
//
#define TEMP_0_PIN 0 // ANALOG A0
#define TEMP_1_PIN 1 // ANALOG A1
#define TEMP_2_PIN 2 // ANALOG A2
#define TEMP_3_PIN 3 // ANALOG A3
#define TEMP_BED_PIN 4 // ANALOG A4
// The thermocouple uses Analog pins
#if ENABLED(VER_WITH_THERMOCOUPLE) // Must be defined in Configuration.h
#define TEMP_4_PIN 5 // A5
#define TEMP_5_PIN 6 // A6 (Marlin 2.0 not support)
#endif
// SPI for Max6675 or Max31855 Thermocouple
/*
#if DISABLED(SDSUPPORT)
#define MAX6675_SS_PIN 53
#else
#define MAX6675_SS_PIN 49
#endif
*/
//
// Misc. Functions
//
#define SDSS 4
#define LED_PIN -1 // 13 - HEATER_0_PIN
#define PS_ON_PIN -1 // 57
// MKS TFT / Nextion Use internal USART-1
#define TFT_LCD_MODULE_COM 1
#define TFT_LCD_MODULE_BAUDRATE 115200
// ESP WiFi Use internal USART-2
#define ESP_WIFI_MODULE_COM 2
#define ESP_WIFI_MODULE_BAUDRATE 115200
#define ESP_WIFI_MODULE_RESET_PIN -1
#define PIGGY_GPIO_PIN -1
//
// EEPROM
//
#define E2END 0x7FFF // 32Kb (24lc256)
#define I2C_EEPROM // EEPROM on I2C
//
// LCD / Controller
//
#if HAS_SPI_LCD
#if EITHER(RADDS_DISPLAY, REPRAP_DISCOUNT_SMART_CONTROLLER)
#define BEEPER_PIN 75
#define LCD_PINS_D4 48
#define LCD_PINS_D7 53
#define SD_DETECT_PIN -1 // 51 can't be used, it's MOSI
#define LCD_PINS_RS 76
#define LCD_PINS_ENABLE 77
#elif ENABLED(REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER)
#define BEEPER_PIN 75
#define LCD_PINS_D4 48
#define SD_DETECT_PIN -1 // 51 can't be used, it's MOSI
#define LCD_PINS_RS 76
#define LCD_PINS_ENABLE 77
#elif HAS_SSD1306_OLED_I2C
#define BEEPER_PIN 75
#define LCD_SDSS 10
#define SD_DETECT_PIN -1 // 51 can't be used, it's MOSI
#elif ENABLED(FYSETC_MINI_12864)
#define BEEPER_PIN 75
#define DOGLCD_CS 77
#define DOGLCD_A0 76
//#define FORCE_SOFT_SPI // Use this if default of hardware SPI causes display problems
// results in LCD soft SPI mode 3, SD soft SPI mode 0
#define LCD_RESET_PIN 48 // Must be high or open for LCD to operate normally.
#if EITHER(FYSETC_MINI_12864_1_2, FYSETC_MINI_12864_2_0)
#error "Pin compatibility check needed! Grand central M4 pins 50, 51 and 52 are not GPIO pins, they are wired to MISO, MOSI, and SCK."
#ifndef RGB_LED_R_PIN
#define RGB_LED_R_PIN 50 // D5
#endif
#ifndef RGB_LED_G_PIN
#define RGB_LED_G_PIN 52 // D6
#endif
#ifndef RGB_LED_B_PIN
#define RGB_LED_B_PIN 53 // D7
#endif
#elif ENABLED(FYSETC_MINI_12864_2_1)
#error "Pin compatibility check needed! Grand central M4 pins 50, 51 and 52 are not GPIO pins, they are wired to MISO, MOSI, and SCK."
#define NEOPIXEL_PIN 50 // D5
#endif
#elif ENABLED(MKS_MINI_12864)
#error "Pin compatibility check needed! Grand central M4 pins 50, 51 and 52 are not GPIO pins, they are wired to MISO, MOSI, and SCK."
#define ORIG_BEEPER_PIN 75
#define DOGLCD_A0 52
#define DOGLCD_CS 50
#define SD_DETECT_PIN -1 // 51 can't be used, it's MOSI
#endif
#if ENABLED(NEWPANEL)
#define BTN_EN1 44
#define BTN_EN2 42
#define BTN_ENC 40
#endif
#endif // HAS_SPI_LCD
//
// SD Support
//
#ifndef SDCARD_CONNECTION
#define SDCARD_CONNECTION ONBOARD
#endif
#if SD_CONNECTION_IS(ONBOARD)
#undef SDSS
#define SDSS 83
#undef SD_DETECT_PIN
#define SD_DETECT_PIN 95
#endif

@ -1,4 +1,4 @@
# Marlin 3D Printer Firmware
# Marlin 3D Printer Firmware
[![Build Status](https://travis-ci.org/MarlinFirmware/Marlin.svg?branch=bugfix-2.0.x)](https://travis-ci.org/MarlinFirmware/Marlin)
![GitHub](https://img.shields.io/github/license/marlinfirmware/marlin.svg)
@ -49,6 +49,7 @@ Marlin 2.0 introduces a layer of abstraction so that all the existing high-level
----|---------|-----|-----|----|-----|---
[STEVAL-3DP001V1](http://www.st.com/en/evaluation-tools/steval-3dp001v1.html)|[STM32F401VE Arm-Cortex M4](http://www.st.com/en/microcontrollers/stm32f401ve.html)|84MHz|512k|64+32k|3.3-5V|yes
[Smoothieboard](http://reprap.org/wiki/Smoothieboard)|LPC1769 ARM-Cortex M3|120MHz|512k|64k|3.3-5V|no
[Adafruit Grand Central M4](https://www.adafruit.com/product/4064)|ARM-Cortex M4|120MHz|1M|256k|3.3V|yes
## Submitting Patches

@ -0,0 +1,14 @@
#!/usr/bin/env bash
#
# Build tests for Adafruit Grand Central M4 (ATMEL ARM Cortex-M4)
#
# exit on first failure
set -e
restore_configs
opt_set MOTHERBOARD BOARD_AGCM4_RURAMPS4D_13
exec_test $1 $2 "Build Grand Central M4 Default Configuration"
# clean up
restore_configs

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1040,7 +1040,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1041,7 +1041,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1045,7 +1045,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1036,7 +1036,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1041,7 +1041,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1041,7 +1041,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1042,7 +1042,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1042,7 +1042,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1038,7 +1038,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1033,7 +1033,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

@ -1037,7 +1037,7 @@
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
//#define BINARY_FILE_TRANSFER
#ifdef TARGET_LPC1768
#if HAS_SDCARD_CONNECTION
/**
* Set this option to one of the following (or the board's defaults apply):
*

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save