1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2025-02-18 15:06:03 +01:00

Merge remote-tracking branch 'origin/TrackManager_SAMD' into PORTX_HAL

This commit is contained in:
Asbelos 2022-07-07 10:02:28 +01:00
commit 385afdeb6c
10 changed files with 68 additions and 22 deletions

View File

@ -1,4 +1,5 @@
/* /*
* © 2022 Paul M Antoine
* © 2021 Neil McKechnie * © 2021 Neil McKechnie
* © 2021 Mike S * © 2021 Mike S
* © 2021 Herb Morton * © 2021 Herb Morton
@ -906,9 +907,15 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[])
wdt_enable( WDTO_15MS); // set Arduino watchdog timer for 15ms wdt_enable( WDTO_15MS); // set Arduino watchdog timer for 15ms
delay(50); // wait for the prescaller time to expire delay(50); // wait for the prescaller time to expire
#else #else
#ifdef ARDUINO_ARCH_ESP #if defined(ARDUINO_ARCH_ESP32)
ESP.restart(); ESP.restart();
#endif #endif
#if defined(ARDUINO_ARCH_SAMD)
// Disable all interrupts and reset uC
__disable_irq();
NVIC_SystemReset();
while(true);
#endif
#endif #endif
break; // and <X> if we didnt restart break; // and <X> if we didnt restart
} }

View File

@ -1,4 +1,5 @@
/* /*
* © 2022 Paul M Antoine
* © 2021 Mike S * © 2021 Mike S
* © 2021 Harald Barth * © 2021 Harald Barth
* © 2021 Fred Decker * © 2021 Fred Decker

View File

@ -1,10 +1,10 @@
/* /*
* © 2022 Paul M Antoine
* © 2021 Mike S * © 2021 Mike S
* © 2021 Harald Barth * © 2021 Harald Barth
* © 2021 Fred Decker * © 2021 Fred Decker
* © 2021 Chris Harlow * © 2021 Chris Harlow
* © 2021 David Cutting * © 2021 David Cutting
* © 2022 Paul M. Antoine
* All rights reserved. * All rights reserved.
* *
* This file is part of Asbelos DCC API * This file is part of Asbelos DCC API
@ -23,7 +23,7 @@
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>. * along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
*/ */
// ATTENTION: this file only compiles on a TEENSY // ATTENTION: this file only compiles on a SAMD21 based board
// Please refer to DCCTimer.h for general comments about how this class works // Please refer to DCCTimer.h for general comments about how this class works
// This is to avoid repetition and duplication. // This is to avoid repetition and duplication.
#ifdef ARDUINO_ARCH_SAMD #ifdef ARDUINO_ARCH_SAMD
@ -38,8 +38,9 @@ void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
interruptHandler=callback; interruptHandler=callback;
noInterrupts(); noInterrupts();
// PMA - Set up ADC to do faster reads... default for Arduino Zero platform configs is 436uS, // Set up ADC to do faster reads... default for Arduino Zero platform configs is 436uS,
// and we need sub-100uS. This code sets it to a read speed of around 21uS, and enables 12-bit // and we need sub-100uS. This code sets it to a read speed of around 21uS, and for now
// enables 10-bit mode, although 12-bit is possible
ADC->CTRLA.bit.ENABLE = 0; // disable ADC ADC->CTRLA.bit.ENABLE = 0; // disable ADC
while( ADC->STATUS.bit.SYNCBUSY == 1 ); // wait for synchronization while( ADC->STATUS.bit.SYNCBUSY == 1 ); // wait for synchronization
@ -54,8 +55,7 @@ void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
ADC->CTRLA.bit.ENABLE = 1; // enable ADC ADC->CTRLA.bit.ENABLE = 1; // enable ADC
while(ADC->STATUS.bit.SYNCBUSY == 1); // wait for synchronization while(ADC->STATUS.bit.SYNCBUSY == 1); // wait for synchronization
// PMA - actual timer setup goo // Timer setup - setup clock sources first
// Setup clock sources first
REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide 48MHz by 1 REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide 48MHz by 1
GCLK_GENDIV_ID(4); // Apply to GCLK4 GCLK_GENDIV_ID(4); // Apply to GCLK4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
@ -70,32 +70,31 @@ void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK to TCC0/1 GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK to TCC0/1
while (GCLK->STATUS.bit.SYNCBUSY); while (GCLK->STATUS.bit.SYNCBUSY);
// PMA - assume we're using TCC0... as we're bit-bashing the DCC waveform output pins anyway // Assume we're using TCC0... as we're bit-bashing the DCC waveform output pins anyway
// for "normal accuracy" DCC waveform generation. For high accuracy we're going to need // for "normal accuracy" DCC waveform generation. For high accuracy we're going to need
// to a good deal more. The TCC waveform output pins are mux'd on the SAMD, and OP pins // to a good deal more. The TCC waveform output pins are mux'd on the SAMD, and output
// for each TCC are only available on certain pins // pins for each TCC are only available on certain pins
TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; // Select NPWM as waveform TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; // Select NPWM as waveform
while (TCC0->SYNCBUSY.bit.WAVE); // Wait for sync while (TCC0->SYNCBUSY.bit.WAVE); // Wait for sync
// PMA - set the frequency // Set the frequency
TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV1_Val); TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV1_Val);
TCC0->PER.reg = CLOCK_CYCLES * 2; TCC0->PER.reg = CLOCK_CYCLES * 2;
while (TCC0->SYNCBUSY.bit.PER); while (TCC0->SYNCBUSY.bit.PER);
// PMA - start it // Start the timer
TCC0->CTRLA.bit.ENABLE = 1; TCC0->CTRLA.bit.ENABLE = 1;
while (TCC0->SYNCBUSY.bit.ENABLE); while (TCC0->SYNCBUSY.bit.ENABLE);
// PMA - set interrupt condition, priority and enable // Set the interrupt condition, priority and enable it in the NVIC
TCC0->INTENSET.reg = TCC_INTENSET_OVF; // Only interrupt on overflow TCC0->INTENSET.reg = TCC_INTENSET_OVF; // Only interrupt on overflow
NVIC_SetPriority((IRQn_Type)TCC0_IRQn, 0); // Make this highest priority NVIC_SetPriority((IRQn_Type)TCC0_IRQn, 0); // Make this highest priority
NVIC_EnableIRQ((IRQn_Type)TCC0_IRQn); // Enable the interrupt NVIC_EnableIRQ((IRQn_Type)TCC0_IRQn); // Enable the interrupt
interrupts(); interrupts();
} }
// PMA - Timer IRQ handlers replace the dummy handlers (cortex_handlers) // Timer IRQ handlers replace the dummy handlers (in cortex_handlers)
// copied from rf24 branch // copied from rf24 branch
// TODO: test
void TCC0_Handler() { void TCC0_Handler() {
if(TCC0->INTFLAG.bit.OVF) { if(TCC0->INTFLAG.bit.OVF) {
TCC0->INTFLAG.bit.OVF = 1; // writing a 1 clears the flag TCC0->INTFLAG.bit.OVF = 1; // writing a 1 clears the flag
@ -126,11 +125,15 @@ bool DCCTimer::isPWMPin(byte pin) {
} }
void DCCTimer::setPWM(byte pin, bool high) { void DCCTimer::setPWM(byte pin, bool high) {
// TODO: what are the relevant pins? // TODO: High Accuracy mode is not supported as yet, and may never need to be
(void) pin; (void) pin;
(void) high; (void) high;
} }
void DCCTimer::clearPWM() {
return;
}
void DCCTimer::getSimulatedMacAddress(byte mac[6]) { void DCCTimer::getSimulatedMacAddress(byte mac[6]) {
volatile uint32_t *serno1 = (volatile uint32_t *)0x0080A00C; volatile uint32_t *serno1 = (volatile uint32_t *)0x0080A00C;
volatile uint32_t *serno2 = (volatile uint32_t *)0x0080A040; volatile uint32_t *serno2 = (volatile uint32_t *)0x0080A040;

View File

@ -26,7 +26,7 @@
#include <Arduino.h> #include <Arduino.h>
#if defined(ARDUINO_ARCH_SAMD) #if defined(ARDUINO_ARCH_SAMC)
#include <SparkFun_External_EEPROM.h> #include <SparkFun_External_EEPROM.h>
extern ExternalEEPROM EEPROM; extern ExternalEEPROM EEPROM;
#else #else

View File

@ -1,4 +1,5 @@
/* /*
* © 2022 Paul M Antoine
* © 2021 Mike S * © 2021 Mike S
* © 2021 Fred Decker * © 2021 Fred Decker
* © 2020-2022 Harald Barth * © 2020-2022 Harald Barth

View File

@ -1,4 +1,5 @@
/* /*
* © 2022 Paul M Antoine
* © 2021 Mike S * © 2021 Mike S
* © 2021 Fred Decker * © 2021 Fred Decker
* © 2020 Chris Harlow * © 2020 Chris Harlow

View File

@ -1,4 +1,5 @@
/* /*
* © 2022 Paul M Antoine
* © 2021 Fred Decker * © 2021 Fred Decker
* © 2020-2022 Harald Barth * © 2020-2022 Harald Barth
* (c) 2020 Chris Harlow. All rights reserved. * (c) 2020 Chris Harlow. All rights reserved.
@ -59,6 +60,13 @@
new MotorDriver(11, 13, UNUSED_PIN, 8, A1, 2.99, 2000, UNUSED_PIN) new MotorDriver(11, 13, UNUSED_PIN, 8, A1, 2.99, 2000, UNUSED_PIN)
#endif #endif
// Setup for SAMD21 Sparkfun DEV board using Arduino standard Motor Shield R3 (MUST be R3 for 3v3 compatibility!!)
// senseFactor for 3.3v systems is 1.95 as calculated when using 10-bit A/D samples,
// and for 12-bit samples it's more like 0.488, but we probably need to tweak both these
#define SAMD_STANDARD_MOTOR_SHIELD F("STANDARD_MOTOR_SHIELD"), \
new MotorDriver(3, 12, UNUSED_PIN, 9, A0, 1.95, 2000, UNUSED_PIN), \
new MotorDriver(11, 13, UNUSED_PIN, 8, A1, 1.95, 2000, UNUSED_PIN)
// Pololu Motor Shield // Pololu Motor Shield
#define POLOLU_MOTOR_SHIELD F("POLOLU_MOTOR_SHIELD"), \ #define POLOLU_MOTOR_SHIELD F("POLOLU_MOTOR_SHIELD"), \
new MotorDriver( 9, 7, UNUSED_PIN, -4, A0, 18, 3000, 12), \ new MotorDriver( 9, 7, UNUSED_PIN, -4, A0, 18, 3000, 12), \

View File

@ -1,4 +1,5 @@
/* /*
* © 2022 Paul M Antoine
* © 2021 Chris Harlow * © 2021 Chris Harlow
* © 2022 Harald Barth * © 2022 Harald Barth
* All rights reserved. * All rights reserved.
@ -33,13 +34,12 @@ SerialManager::SerialManager(Stream * myserial) {
} }
void SerialManager::init() { void SerialManager::init() {
// while (!Serial && millis() < 5000); // wait max 5s for Serial to start
#if defined(ARDUINO_ARCH_SAMD) #if defined(ARDUINO_ARCH_SAMD)
SerialUSB.begin(115200); SerialUSB.begin(115200);
while (!SerialUSB); // PMA - temporary for debuggering purpoises
new SerialManager(&SerialUSB); new SerialManager(&SerialUSB);
#else #else
Serial.begin(115200); Serial.begin(115200);
while (!Serial && millis() < 5000); // wait max 5s for Serial to start
new SerialManager(&Serial); new SerialManager(&Serial);
#endif #endif
#ifdef SERIAL3_COMMANDS #ifdef SERIAL3_COMMANDS

View File

@ -1,4 +1,5 @@
/* /*
* © 2022 Paul M Antoine
* © 2021 Neil McKechnie * © 2021 Neil McKechnie
* © 2021 Mike S * © 2021 Mike S
* © 2021 Fred Decker * © 2021 Fred Decker

View File

@ -15,23 +15,47 @@ default_envs =
mega328 mega328
unowifiR2 unowifiR2
nano nano
samd21-dev-usb
samd21-zero-usb
src_dir = . src_dir = .
include_dir = . include_dir = .
[env] [env]
build_flags = -Wall -Wextra build_flags = -Wall -Wextra
[env:samd21] [env:samd21-dev-usb]
platform = atmelsam platform = atmelsam
board = sparkfun_samd21_dev_usb board = sparkfun_samd21_dev_usb
framework = arduino framework = arduino
upload_protocol = sam-ba upload_protocol = sam-ba
lib_deps =
${env.lib_deps}
monitor_speed = 115200
monitor_flags = --echo
build_flags = -std=c++17 -DI2C_USE_WIRE -DDISABLE_EEPROM
[env:samd21-zero-usb]
platform = atmelsam
board = zeroUSB
framework = arduino
upload_protocol = sam-ba
lib_deps =
${env.lib_deps}
monitor_speed = 115200
monitor_flags = --echo
build_flags = -std=c++17 -DI2C_USE_WIRE -DDISABLE_EEPROM
[env:samc21-firebox]
platform = atmelsam
board = firebox
framework = arduino
upload_protocol = atmel-ice
lib_deps = lib_deps =
${env.lib_deps} ${env.lib_deps}
SparkFun External EEPROM Arduino Library SparkFun External EEPROM Arduino Library
monitor_speed = 115200 monitor_speed = 115200
monitor_flags = --echo monitor_flags = --echo
build_flags = -std=c++17 build_flags = -std=c++17 -DI2C_USE_WIRE -DDISABLE_EEPROM
[env:mega2560-debug] [env:mega2560-debug]
platform = atmelavr platform = atmelavr