1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-23 16:16:13 +01:00

Merge pull request #4 from DCC-EX/master

update from upstream
This commit is contained in:
mstevetodd 2020-11-21 11:39:41 -05:00 committed by GitHub
commit 7d460e5ef1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 13 additions and 536 deletions

View File

@ -1,131 +0,0 @@
#ifndef ATMEGA328Timer_h
#define ATMEGA328Timer_h
#include "../VirtualTimer.h"
#include <Arduino.h>
// We only define behavior for timer 0 (TCA0), because TCB0 is very limited in functionality.
class Timer : public VirtualTimer {
private:
int pwmPeriod;
unsigned long timer_resolution;
unsigned char clockSelectBits;
int timer_num;
unsigned long lastMicroseconds;
public:
void (*isrCallback)();
Timer(int timer_num) {
switch (timer_num)
{
case 0:
timer_resolution = 65536;
break;
}
this->timer_num = timer_num;
lastMicroseconds = 0;
}
void initialize() {
switch (timer_num)
{
case 0:
break;
}
}
void setPeriod(unsigned long microseconds) {
if(microseconds == lastMicroseconds)
return;
lastMicroseconds = microseconds;
const unsigned long cycles = (F_CPU / 1000000) * microseconds;
switch(timer_num) {
case 0:
if (cycles < timer_resolution) {
clockSelectBits = 0x0;
pwmPeriod = cycles;
} else
if (cycles < timer_resolution * 2) {
clockSelectBits = 0x1;
pwmPeriod = cycles / 8;
} else
if (cycles < timer_resolution * 4) {
clockSelectBits = 0x2;
pwmPeriod = cycles / 32;
} else
if (cycles < timer_resolution * 8) {
clockSelectBits = 0x3;
pwmPeriod = cycles / 64;
} else
if (cycles < timer_resolution * 64) {
clockSelectBits = 0x5;
pwmPeriod = cycles / 128;
} else
if (cycles < timer_resolution * 256) {
clockSelectBits = 0x6;
pwmPeriod = cycles / 256;
} else
if (cycles < timer_resolution * 1024) {
clockSelectBits = 0x7;
pwmPeriod = cycles / 1024;
} else {
clockSelectBits = 0x7;
pwmPeriod = timer_resolution - 1;
}
break;
}
switch (timer_num)
{
case 0:
TCA0.SINGLE.PER = pwmPeriod;
TCA0.SINGLE.CTRLA = clockSelectBits << 1;
break;
}
}
void start() {
switch (timer_num)
{
case 0:
bitSet(TCA0.SINGLE.CTRLA, 0);
break;
}
}
void stop() {
switch (timer_num)
{
case 0:
bitClear(TCA0.SINGLE.CTRLA, 0);
break;
}
}
void attachInterrupt(void (*isr)()) {
isrCallback = isr;
switch (timer_num)
{
case 0:
TCA0.SINGLE.INTCTRL = 0x1;
break;
}
}
void detachInterrupt() {
switch (timer_num)
{
case 0:
TCA0.SINGLE.INTCTRL = 0x0;
break;
}
}
};
extern Timer TimerA;
#endif

View File

@ -1,129 +0,0 @@
#ifndef ATSAMC21Timer_h
#define ATSAMC21Timer_h
#include "../VirtualTimer.h"
#include <Arduino.h>
class Timer : public VirtualTimer
{
private:
int pwmPeriod;
unsigned long timer_resolution;
unsigned long lastMicroseconds;
public:
void (*isrCallback)();
Tcc* timer;
Timer(Tcc* timer) {
this->timer = timer;
if(timer == TCC0 || timer == TCC1) {
timer_resolution = 16777216;
} else {
timer_resolution = 65536;
}
lastMicroseconds = 0;
}
void initialize() {
if(timer == TCC0 || timer == TCC1) {
MCLK->APBCMASK.bit.TCC0_ = 1;
MCLK->APBCMASK.bit.TCC1_ = 1;
GCLK->GENCTRL[4].reg = ( GCLK_GENCTRL_DIV(2) | GCLK_GENCTRL_SRC_DPLL96M | GCLK_GENCTRL_IDC | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_OE );
while ((GCLK->SYNCBUSY.bit.GENCTRL >> 4) & 1); // Wait for synchronization
GCLK->PCHCTRL[28].reg = ( GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(4) ); // 28 = TCC0_TCC1
while ((GCLK->SYNCBUSY.bit.GENCTRL >> 4) & 1); // Wait for synchronization
}
else if (timer == TCC2) {
MCLK->APBCMASK.bit.TCC2_ = 1;
GCLK->GENCTRL[5].reg = ( GCLK_GENCTRL_DIV(2) | GCLK_GENCTRL_SRC_DPLL96M | GCLK_GENCTRL_IDC | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_OE );
while ((GCLK->SYNCBUSY.bit.GENCTRL >> 5) & 1); // Wait for synchronization
GCLK->PCHCTRL[29].reg = ( GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(5) ); // 29 = TCC2
while ((GCLK->SYNCBUSY.bit.GENCTRL >> 5) & 1); // Wait for synchronization
}
timer->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; // Select NPWM as waveform
while (timer->SYNCBUSY.bit.WAVE); // Wait for synchronization
}
void setPeriod(unsigned long microseconds) {
if(microseconds == lastMicroseconds)
return;
lastMicroseconds = microseconds;
const unsigned long cycles = F_CPU / 1000000 * microseconds; // cycles corresponds to how many clock ticks per microsecond times number of microseconds we want
timer->CTRLA.bit.PRESCALER = 0;
if(cycles < timer_resolution) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV1_Val);
pwmPeriod = cycles;
} else
if(cycles < timer_resolution * 2) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV2_Val);
pwmPeriod = cycles / 2;
} else
if(cycles < timer_resolution * 4) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV4_Val);
pwmPeriod = cycles / 4;
} else
if(cycles < timer_resolution * 8) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV8_Val);
pwmPeriod = cycles / 8;
} else
if(cycles < timer_resolution * 16) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV16_Val);
pwmPeriod = cycles / 16;
} else
if(cycles < timer_resolution * 64) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV64_Val);
pwmPeriod = cycles / 64;
} else
if(cycles < timer_resolution * 1024) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV1024_Val);
pwmPeriod = cycles / 1024;
}
timer->PER.reg = pwmPeriod;
while (timer->SYNCBUSY.bit.PER);
}
void start() {
timer->CTRLA.bit.ENABLE = 1; // Turn on the output
while (timer->SYNCBUSY.bit.ENABLE); // Wait for synchronization
}
void stop() {
timer->CTRLA.bit.ENABLE = 0; // Turn on the output
while (timer->SYNCBUSY.bit.ENABLE); // Wait for synchronization
}
void attachInterrupt(void (*isr)()) {
isrCallback = isr; // Store the interrupt callback function
timer->INTENSET.reg = TCC_INTENSET_OVF; // Set the interrupt to occur on overflow
if(timer == TCC0) {
NVIC_EnableIRQ((IRQn_Type) TCC0_IRQn); // Enable the interrupt (clock is still off)
}
else if(timer == TCC1) {
NVIC_EnableIRQ((IRQn_Type) TCC1_IRQn); // Enable the interrupt (clock is still off)
}
else if(timer == TCC2) {
NVIC_EnableIRQ((IRQn_Type) TCC2_IRQn); // Enable the interrupt (clock is still off)
}
}
void detachInterrupt() {
if(timer == TCC0) {
NVIC_DisableIRQ((IRQn_Type) TCC0_IRQn); // Disable the interrupt
}
else if(timer == TCC1) {
NVIC_DisableIRQ((IRQn_Type) TCC1_IRQn); // Disable the interrupt
}
else if(timer == TCC2) {
NVIC_DisableIRQ((IRQn_Type) TCC2_IRQn); // Disable the interrupt
}
}
};
extern Timer TimerA;
extern Timer TimerB;
extern Timer TimerC;
#endif // ATSAMC21Timer_h

View File

@ -1,144 +0,0 @@
#ifndef ATSAMD21GTimer_h
#define ATSAMD21GTimer_h
#include "../VirtualTimer.h"
#include <Arduino.h>
class Timer : public VirtualTimer
{
private:
int pwmPeriod;
unsigned long timer_resolution;
unsigned long lastMicroseconds;
public:
void (*isrCallback)();
Tcc* timer;
Timer(Tcc* timer) {
this->timer = timer;
if(timer == TCC0 || timer == TCC1) {
timer_resolution = 16777216;
} else {
timer_resolution = 65536;
}
lastMicroseconds = 0;
}
void initialize() {
if(timer == TCC0 || timer == TCC1) {
REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide 48MHz by 1
GCLK_GENDIV_ID(4); // Apply to GCLK4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_GCLK_GENCTRL = GCLK_GENCTRL_GENEN | // Enable GCLK
GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source
GCLK_GENCTRL_ID(4); // Select GCLK4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable generic clock
4 << GCLK_CLKCTRL_GEN_Pos | // Apply to GCLK4
GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK to TCC0/1
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
}
else if (timer == TCC2) {
REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide 48MHz by 1
GCLK_GENDIV_ID(5); // Apply to GCLK4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_GCLK_GENCTRL = GCLK_GENCTRL_GENEN | // Enable GCLK
GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source
GCLK_GENCTRL_ID(5); // Select GCLK4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable generic clock
5 << GCLK_CLKCTRL_GEN_Pos | // Apply to GCLK4
GCLK_CLKCTRL_ID_TCC2_TC3; // Feed GCLK to TCC0/1
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
}
timer->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; // Select NPWM as waveform
while (timer->SYNCBUSY.bit.WAVE); // Wait for synchronization
}
void setPeriod(unsigned long microseconds) {
if(microseconds == lastMicroseconds)
return;
lastMicroseconds = microseconds;
const unsigned long cycles = F_CPU / 1000000 * microseconds; // cycles corresponds to how many clock ticks per microsecond times number of microseconds we want
if(cycles < timer_resolution) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV1_Val);
pwmPeriod = cycles;
} else
if(cycles < timer_resolution * 2) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV2_Val);
pwmPeriod = cycles / 2;
} else
if(cycles < timer_resolution * 4) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV4_Val);
pwmPeriod = cycles / 4;
} else
if(cycles < timer_resolution * 8) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV8_Val);
pwmPeriod = cycles / 8;
} else
if(cycles < timer_resolution * 16) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV16_Val);
pwmPeriod = cycles / 16;
} else
if(cycles < timer_resolution * 64) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV64_Val);
pwmPeriod = cycles / 64;
} else
if(cycles < timer_resolution * 1024) {
timer->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV1024_Val);
pwmPeriod = cycles / 1024;
}
timer->PER.reg = pwmPeriod;
while (timer->SYNCBUSY.bit.PER);
}
void start() {
timer->CTRLA.bit.ENABLE = 1; // Turn on the output
while (timer->SYNCBUSY.bit.ENABLE); // Wait for synchronization
}
void stop() {
timer->CTRLA.bit.ENABLE = 0; // Turn on the output
while (timer->SYNCBUSY.bit.ENABLE); // Wait for synchronization
}
void attachInterrupt(void (*isr)()) {
isrCallback = isr; // Store the interrupt callback function
timer->INTENSET.reg = TCC_INTENSET_OVF; // Set the interrupt to occur on overflow
if(timer == TCC0) {
NVIC_EnableIRQ((IRQn_Type) TCC0_IRQn); // Enable the interrupt (clock is still off)
}
else if(timer == TCC1) {
NVIC_EnableIRQ((IRQn_Type) TCC1_IRQn); // Enable the interrupt (clock is still off)
}
else if(timer == TCC2) {
NVIC_EnableIRQ((IRQn_Type) TCC2_IRQn); // Enable the interrupt (clock is still off)
}
}
void detachInterrupt() {
if(timer == TCC0) {
NVIC_DisableIRQ((IRQn_Type) TCC0_IRQn); // Disable the interrupt
}
else if(timer == TCC1) {
NVIC_DisableIRQ((IRQn_Type) TCC1_IRQn); // Disable the interrupt
}
else if(timer == TCC2) {
NVIC_DisableIRQ((IRQn_Type) TCC2_IRQn); // Disable the interrupt
}
}
};
extern Timer TimerA;
extern Timer TimerB;
extern Timer TimerC;
#endif

View File

@ -26,81 +26,6 @@
int inline analogReadFast(uint8_t ADCpin);
#if defined(ARDUINO_ARCH_SAMD)
int inline analogReadFast(uint8_t ADCpin)
{ ADC->CTRLA.bit.ENABLE = 0; // disable ADC
while( ADC->STATUS.bit.SYNCBUSY == 1 ); // wait for synchronization
int CTRLBoriginal = ADC->CTRLB.reg;
int AVGCTRLoriginal = ADC->AVGCTRL.reg;
int SAMPCTRLoriginal = ADC->SAMPCTRL.reg;
ADC->CTRLB.reg &= 0b1111100011111111; // mask PRESCALER bits
ADC->CTRLB.reg |= ADC_CTRLB_PRESCALER_DIV64; // divide Clock by 64
ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_1 | // take 1 sample
ADC_AVGCTRL_ADJRES(0x00ul); // adjusting result by 0
ADC->SAMPCTRL.reg = 0x00; // sampling Time Length = 0
ADC->CTRLA.bit.ENABLE = 1; // enable ADC
while(ADC->STATUS.bit.SYNCBUSY == 1); // wait for synchronization
int adc = analogRead(ADCpin);
ADC->CTRLB.reg = CTRLBoriginal;
ADC->AVGCTRL.reg = AVGCTRLoriginal;
ADC->SAMPCTRL.reg = SAMPCTRLoriginal;
return adc;
}
#elif defined(ARDUINO_ARCH_SAMC)
int inline analogReadFast(uint8_t ADCpin)
{
Adc* ADC;
if ( (g_APinDescription[ADCpin].ulPeripheralAttribute & PER_ATTR_ADC_MASK) == PER_ATTR_ADC_STD ) {
ADC = ADC0;
} else {
ADC = ADC1;
}
ADC->CTRLA.bit.ENABLE = 0; // disable ADC
while( ADC->SYNCBUSY.bit.ENABLE == 1 ); // wait for synchronization
int CTRLBoriginal = ADC->CTRLB.reg;
int AVGCTRLoriginal = ADC->AVGCTRL.reg;
int SAMPCTRLoriginal = ADC->SAMPCTRL.reg;
ADC->CTRLB.reg &= 0b1111100011111111; // mask PRESCALER bits
ADC->CTRLB.reg |= ADC_CTRLB_PRESCALER_DIV64; // divide Clock by 64
ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_1 | // take 1 sample
ADC_AVGCTRL_ADJRES(0x00ul); // adjusting result by 0
ADC->SAMPCTRL.reg = 0x00; // sampling Time Length = 0
ADC->CTRLA.bit.ENABLE = 1; // enable ADC
while(ADC->SYNCBUSY.bit.ENABLE == 1); // wait for synchronization
int adc = analogRead(ADCpin);
ADC->CTRLB.reg = CTRLBoriginal;
ADC->AVGCTRL.reg = AVGCTRLoriginal;
ADC->SAMPCTRL.reg = SAMPCTRLoriginal;
return adc;
}
#elif defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_AVR_NANO_EVERY)
int inline analogReadFast(uint8_t ADCpin)
{ byte ADC0CTRLCoriginal = ADC0.CTRLC;
ADC0.CTRLC = (ADC0CTRLCoriginal & 0b00110000) + 0b01000011;
int adc = analogRead(ADCpin);
ADC0.CTRLC = ADC0CTRLCoriginal;
return adc;
}
#else
int inline analogReadFast(uint8_t ADCpin)
{ byte ADCSRAoriginal = ADCSRA;
ADCSRA = (ADCSRA & B11111000) | 4;
@ -108,5 +33,5 @@ int inline analogReadFast(uint8_t ADCpin)
ADCSRA = ADCSRAoriginal;
return adc;
}
#endif
#endif // COMMANDSTATION_DCC_ANALOGREADFAST_H_

View File

@ -7,16 +7,10 @@
#ifndef ArduinoTimers_h
#define ArduinoTimers_h
#if defined(SAMC21)
#include "ATSAMC21G/Timer.h"
#elif defined(ARDUINO_SAMD_ZERO)
#include "ATSAMD21G/Timer.h"
#elif defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
#include "ATMEGA2560/Timer.h"
#elif defined(ARDUINO_AVR_UNO)
#include "ATMEGA328/Timer.h"
#elif defined(ARDUINO_ARCH_MEGAAVR)
#include "ATMEGA4809/Timer.h"
#else
#error "Cannot compile - ArduinoTimers library does not support your board, or you are missing compatible build flags."
#endif

4
DCC.h
View File

@ -155,10 +155,6 @@ private:
#define ARDUINO_TYPE "NANO"
#elif defined(ARDUINO_AVR_MEGA2560)
#define ARDUINO_TYPE "MEGA"
#elif defined(ARDUINO_ARCH_MEGAAVR)
#define ARDUINO_TYPE "UNOWIFIR2"
#elif defined(ARDUINO_SAMD_ZERO)
#define ARDUINO_TYPE "FireBoxMK1"
#else
#error CANNOT COMPILE - DCC++ EX ONLY WORKS WITH AN ARDUINO UNO, NANO 328, OR ARDUINO MEGA 1280/2560
#endif

View File

@ -515,7 +515,7 @@ bool DCCEXParser::parseT(Print *stream, int params, int p[])
for (Turnout *tt = Turnout::firstTurnout; tt != NULL; tt = tt->nextTurnout)
{
gotOne = true;
StringFormatter::send(stream, F("<H %d %d>"), tt->data.id, tt->data.tStatus & STATUS_ACTIVE);
StringFormatter::send(stream, F("<H %d %d>"), tt->data.id, (tt->data.tStatus & STATUS_ACTIVE)!=0);
}
return gotOne; // will <X> if none found
}
@ -532,7 +532,7 @@ bool DCCEXParser::parseT(Print *stream, int params, int p[])
if (!tt)
return false;
tt->activate(p[1]);
StringFormatter::send(stream, F("<H %d %d>"), tt->data.id, tt->data.tStatus & STATUS_ACTIVE);
StringFormatter::send(stream, F("<H %d %d>"), tt->data.id, (tt->data.tStatus & STATUS_ACTIVE)!=0);
}
return true;

View File

@ -3,39 +3,7 @@
#include <Arduino.h>
#if defined(ARDUINO_SAMD_ZERO)
#if defined(SAMC21)
#include "ATSAMC21G/Timer.h"
#else
#include "ATSAMD21G/Timer.h"
#endif
Timer TimerA(TCC0);
Timer TimerB(TCC1);
Timer TimerC(TCC2);
void TCC0_Handler() {
if(TCC0->INTFLAG.bit.OVF) {
TCC0->INTFLAG.bit.OVF = 1;
TimerA.isrCallback();
}
}
void TCC1_Handler() {
if(TCC1->INTFLAG.bit.OVF) {
TCC1->INTFLAG.bit.OVF = 1;
TimerB.isrCallback();
}
}
void TCC2_Handler() {
if(TCC2->INTFLAG.bit.OVF) {
TCC2->INTFLAG.bit.OVF = 1;
TimerC.isrCallback();
}
}
#elif defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
#include "ATMEGA2560/Timer.h"
@ -81,14 +49,4 @@ ISR(TIMER2_OVF_vect)
TimerB.isrCallback();
}
#elif defined(ARDUINO_ARCH_MEGAAVR)
#include "ATMEGA4809/Timer.h"
Timer TimerA(0);
ISR(TCA0_OVF_vect) {
TimerA.isrCallback();
}
#endif

View File

@ -130,6 +130,11 @@ wifiSerialState WifiInterface::setup(Stream & setupStream, const __FlashStringH
return wifiState;
}
#ifdef DONT_TOUCH_WIFI_CONF
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
wifiSerialState WifiInterface::setup2(const __FlashStringHelper* SSid, const __FlashStringHelper* password,
const __FlashStringHelper* hostname, int port) {
bool ipOK = false;
@ -267,6 +272,9 @@ wifiSerialState WifiInterface::setup2(const __FlashStringHelper* SSid, const __F
return WIFI_CONNECTED;
}
#ifdef DONT_TOUCH_WIFI_CONF
#pragma GCC diagnostic pop
#endif
// This function is used to allow users to enter <+ commands> through the DCCEXParser