Giuliano Zaro
6 years ago
committed by
Scott Lahteine
125 changed files with 2555 additions and 99 deletions
@ -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 can’t 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; |
|||
} |
@ -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 |
@ -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 |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue