mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-23 08:06:13 +01:00
variable frequency step #1
This commit is contained in:
parent
bd44184f57
commit
adb8b56c92
|
@ -85,6 +85,7 @@ class DCCTimer {
|
||||||
static void reset();
|
static void reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t frequency);
|
||||||
static int freeMemory();
|
static int freeMemory();
|
||||||
static volatile int minimum_free_memory;
|
static volatile int minimum_free_memory;
|
||||||
static const int DCC_SIGNAL_TIME=58; // this is the 58uS DCC 1-bit waveform half-cycle
|
static const int DCC_SIGNAL_TIME=58; // this is the 58uS DCC 1-bit waveform half-cycle
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <avr/boot.h>
|
#include <avr/boot.h>
|
||||||
#include <avr/wdt.h>
|
#include <avr/wdt.h>
|
||||||
#include "DCCTimer.h"
|
#include "DCCTimer.h"
|
||||||
|
#include "DIAG.h"
|
||||||
#ifdef DEBUG_ADC
|
#ifdef DEBUG_ADC
|
||||||
#include "TrackManager.h"
|
#include "TrackManager.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -125,6 +126,76 @@ void DCCTimer::reset() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) {
|
||||||
|
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, f);
|
||||||
|
}
|
||||||
|
void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t fbits) {
|
||||||
|
#if defined(ARDUINO_AVR_UNO)
|
||||||
|
// Not worth doin something here as:
|
||||||
|
// If we are on pin 9 or 10 we are on Timer1 and we can not touch Timer1 as that is our DCC source.
|
||||||
|
// If we are on pin 5 or 6 we are on Timer 0 ad we can not touch Timer0 as that is millis() etc.
|
||||||
|
// We are most likely not on pin 3 or 11 as no known motor shield has that as brake.
|
||||||
|
#endif
|
||||||
|
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
|
||||||
|
uint8_t abits;
|
||||||
|
uint8_t bbits;
|
||||||
|
if (pin == 9 || pin == 10) { // timer 2 is different
|
||||||
|
|
||||||
|
if (fbits >= 3)
|
||||||
|
abits = B11;
|
||||||
|
else
|
||||||
|
abits = B01;
|
||||||
|
|
||||||
|
if (fbits >= 3)
|
||||||
|
bbits = B0001;
|
||||||
|
else if (fbits == 2)
|
||||||
|
bbits = B0010;
|
||||||
|
else if (fbits == 1)
|
||||||
|
bbits = B0100;
|
||||||
|
else
|
||||||
|
bbits = B0110;
|
||||||
|
|
||||||
|
TCCR2A = (TCCR2A & B11111100) | abits; // set WGM0 and WGM1
|
||||||
|
TCCR2B = (TCCR2B & B11110000) | bbits; // set WGM2 and 3 bits of prescaler
|
||||||
|
DIAG(F("Timer 2 A=%x B=%x"), TCCR2A, TCCR2B);
|
||||||
|
|
||||||
|
} else { // not timer 9 or 10
|
||||||
|
abits = B01;
|
||||||
|
|
||||||
|
if (fbits >= 3)
|
||||||
|
bbits = B1001;
|
||||||
|
else if (fbits == 2)
|
||||||
|
bbits = B0010;
|
||||||
|
else if (fbits == 1)
|
||||||
|
bbits = B0011;
|
||||||
|
else
|
||||||
|
bbits = B0100;
|
||||||
|
|
||||||
|
switch (pin) {
|
||||||
|
// case 9 and 10 taken care of above by if()
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
case 8:
|
||||||
|
// Timer4
|
||||||
|
TCCR4A = (TCCR4A & B11111100) | abits; // set WGM0 and WGM1
|
||||||
|
TCCR4B = (TCCR4B & B11100000) | bbits; // set WGM2 and WGM3 and divisor
|
||||||
|
DIAG(F("Timer 4 A=%x B=%x"), TCCR4A, TCCR4B);
|
||||||
|
break;
|
||||||
|
case 46:
|
||||||
|
case 45:
|
||||||
|
case 44:
|
||||||
|
// Timer5
|
||||||
|
TCCR5A = (TCCR5A & B11111100) | abits; // set WGM0 and WGM1
|
||||||
|
TCCR5B = (TCCR5B & B11100000) | bbits; // set WGM2 and WGM3 and divisor
|
||||||
|
DIAG(F("Timer 5 A=%x B=%x"), TCCR5A, TCCR5B);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
|
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
|
||||||
#define NUM_ADC_INPUTS 16
|
#define NUM_ADC_INPUTS 16
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -151,10 +151,22 @@ void DCCTimer::reset() {
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) {
|
||||||
|
if (f >= 16)
|
||||||
|
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, f);
|
||||||
|
else if (f >= 3)
|
||||||
|
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 62500);
|
||||||
|
else if (f == 2)
|
||||||
|
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 3400);
|
||||||
|
else if (f == 1)
|
||||||
|
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 480);
|
||||||
|
else
|
||||||
|
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 131);
|
||||||
|
}
|
||||||
|
|
||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef SOC_LEDC_SUPPORT_HS_MODE
|
#ifdef SOC_LEDC_SUPPORT_HS_MODE
|
||||||
#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM<<1)
|
#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM<<1)
|
||||||
#else
|
#else
|
||||||
|
@ -164,7 +176,7 @@ void DCCTimer::reset() {
|
||||||
static int8_t pin_to_channel[SOC_GPIO_PIN_COUNT] = { 0 };
|
static int8_t pin_to_channel[SOC_GPIO_PIN_COUNT] = { 0 };
|
||||||
static int cnt_channel = LEDC_CHANNELS;
|
static int cnt_channel = LEDC_CHANNELS;
|
||||||
|
|
||||||
void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t frequency) {
|
void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t frequency) {
|
||||||
if (pin < SOC_GPIO_PIN_COUNT) {
|
if (pin < SOC_GPIO_PIN_COUNT) {
|
||||||
if (pin_to_channel[pin] != 0) {
|
if (pin_to_channel[pin] != 0) {
|
||||||
ledcSetup(pin_to_channel[pin], frequency, 8);
|
ledcSetup(pin_to_channel[pin], frequency, 8);
|
||||||
|
|
|
@ -257,6 +257,19 @@ void DCCTimer::reset() {
|
||||||
while(true) {};
|
while(true) {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) {
|
||||||
|
if (f >= 16)
|
||||||
|
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, f);
|
||||||
|
else if (f >= 3)
|
||||||
|
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 62500);
|
||||||
|
else if (f == 2)
|
||||||
|
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 3400);
|
||||||
|
else if (f == 1)
|
||||||
|
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 480);
|
||||||
|
else
|
||||||
|
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 131);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: rationalise the size of these... could really use sparse arrays etc.
|
// TODO: rationalise the size of these... could really use sparse arrays etc.
|
||||||
static HardwareTimer * pin_timer[100] = {0};
|
static HardwareTimer * pin_timer[100] = {0};
|
||||||
static uint32_t channel_frequency[100] = {0};
|
static uint32_t channel_frequency[100] = {0};
|
||||||
|
@ -267,7 +280,7 @@ static uint32_t pin_channel[100] = {0};
|
||||||
// sophisticated about detecting any clash between the timer we'd like to use for PWM and the ones
|
// sophisticated about detecting any clash between the timer we'd like to use for PWM and the ones
|
||||||
// currently used for HA so they don't interfere with one another. For now we'll just make PWM
|
// currently used for HA so they don't interfere with one another. For now we'll just make PWM
|
||||||
// work well... then work backwards to integrate with HA mode if we can.
|
// work well... then work backwards to integrate with HA mode if we can.
|
||||||
void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t frequency)
|
void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t frequency)
|
||||||
{
|
{
|
||||||
if (pin_timer[pin] == NULL) {
|
if (pin_timer[pin] == NULL) {
|
||||||
// Automatically retrieve TIM instance and channel associated to pin
|
// Automatically retrieve TIM instance and channel associated to pin
|
||||||
|
|
|
@ -328,45 +328,19 @@ uint16_t taurustones[28] = { 165, 175, 196, 220,
|
||||||
void MotorDriver::setDCSignal(byte speedcode) {
|
void MotorDriver::setDCSignal(byte speedcode) {
|
||||||
if (brakePin == UNUSED_PIN)
|
if (brakePin == UNUSED_PIN)
|
||||||
return;
|
return;
|
||||||
switch(brakePin) {
|
|
||||||
#if defined(ARDUINO_AVR_UNO)
|
|
||||||
// Not worth doin something here as:
|
|
||||||
// If we are on pin 9 or 10 we are on Timer1 and we can not touch Timer1 as that is our DCC source.
|
|
||||||
// If we are on pin 5 or 6 we are on Timer 0 ad we can not touch Timer0 as that is millis() etc.
|
|
||||||
// We are most likely not on pin 3 or 11 as no known motor shield has that as brake.
|
|
||||||
#endif
|
|
||||||
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
|
|
||||||
case 9:
|
|
||||||
case 10:
|
|
||||||
// Timer2 (is differnet)
|
|
||||||
TCCR2A = (TCCR2A & B11111100) | B00000001; // set WGM1=0 and WGM0=1 phase correct PWM
|
|
||||||
TCCR2B = (TCCR2B & B11110000) | B00000110; // set WGM2=0 ; set divisor on timer 2 to 1/256 for 122.55Hz
|
|
||||||
//DIAG(F("2 A=%x B=%x"), TCCR2A, TCCR2B);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
case 7:
|
|
||||||
case 8:
|
|
||||||
// Timer4
|
|
||||||
TCCR4A = (TCCR4A & B11111100) | B00000001; // set WGM0=1 and WGM1=0 for normal PWM 8-bit
|
|
||||||
TCCR4B = (TCCR4B & B11100000) | B00000100; // set WGM2=0 and WGM3=0 for normal PWM 8 bit and div 1/256 for 122.55Hz
|
|
||||||
break;
|
|
||||||
case 46:
|
|
||||||
case 45:
|
|
||||||
case 44:
|
|
||||||
// Timer5
|
|
||||||
TCCR5A = (TCCR5A & B11111100) | B00000001; // set WGM0=1 and WGM1=0 for normal PWM 8-bit
|
|
||||||
TCCR5B = (TCCR5B & B11100000) | B00000100; // set WGM2=0 and WGM3=0 for normal PWM 8 bit and div 1/256 for 122.55Hz
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// spedcoode is a dcc speed & direction
|
// spedcoode is a dcc speed & direction
|
||||||
byte tSpeed=speedcode & 0x7F; // DCC Speed with 0,1 stop and speed steps 2 to 127
|
byte tSpeed=speedcode & 0x7F; // DCC Speed with 0,1 stop and speed steps 2 to 127
|
||||||
byte tDir=speedcode & 0x80;
|
byte tDir=speedcode & 0x80;
|
||||||
byte brake;
|
byte brake;
|
||||||
|
|
||||||
|
if (tSpeed <= 1) brake = 255;
|
||||||
|
else if (tSpeed >= 127) brake = 0;
|
||||||
|
else brake = 2 * (128-tSpeed);
|
||||||
|
if (invertBrake)
|
||||||
|
brake=255-brake;
|
||||||
|
|
||||||
|
{ // new block because of variable f
|
||||||
#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_STM32)
|
#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_STM32)
|
||||||
{
|
|
||||||
int f = 131;
|
int f = 131;
|
||||||
#ifdef VARIABLE_TONES
|
#ifdef VARIABLE_TONES
|
||||||
if (tSpeed > 2) {
|
if (tSpeed > 2) {
|
||||||
|
@ -376,18 +350,13 @@ void MotorDriver::setDCSignal(byte speedcode) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
DCCTimer::DCCEXanalogWriteFrequency(brakePin, f); // set DC PWM frequency to 100Hz XXX May move to setup
|
DCCTimer::DCCEXanalogWriteFrequency(brakePin, f); // set DC PWM frequency to 100Hz XXX May move to setup
|
||||||
|
DCCTimer::DCCEXanalogWrite(brakePin,brake);
|
||||||
|
#else // all AVR here
|
||||||
|
DCCTimer::DCCEXanalogWriteFrequency(brakePin, 0); // 0 is lowest possible f, like 120Hz
|
||||||
|
analogWrite(brakePin,brake);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (tSpeed <= 1) brake = 255;
|
|
||||||
else if (tSpeed >= 127) brake = 0;
|
|
||||||
else brake = 2 * (128-tSpeed);
|
|
||||||
if (invertBrake)
|
|
||||||
brake=255-brake;
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_STM32)
|
|
||||||
DCCTimer::DCCEXanalogWrite(brakePin,brake);
|
|
||||||
#else
|
|
||||||
analogWrite(brakePin,brake);
|
|
||||||
#endif
|
|
||||||
//DIAG(F("DCSignal %d"), speedcode);
|
//DIAG(F("DCSignal %d"), speedcode);
|
||||||
if (HAVE_PORTA(fastSignalPin.shadowinout == &PORTA)) {
|
if (HAVE_PORTA(fastSignalPin.shadowinout == &PORTA)) {
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
|
@ -455,39 +424,7 @@ void MotorDriver::throttleInrush(bool on) {
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if(on){
|
if(on){
|
||||||
switch(brakePin) {
|
DCCTimer::DCCEXanalogWriteFrequency(brakePin, 3);
|
||||||
#if defined(ARDUINO_AVR_UNO)
|
|
||||||
// Not worth doin something here as:
|
|
||||||
// If we are on pin 9 or 10 we are on Timer1 and we can not touch Timer1 as that is our DCC source.
|
|
||||||
// If we are on pin 5 or 6 we are on Timer 0 ad we can not touch Timer0 as that is millis() etc.
|
|
||||||
// We are most likely not on pin 3 or 11 as no known motor shield has that as brake.
|
|
||||||
#endif
|
|
||||||
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
|
|
||||||
case 9:
|
|
||||||
case 10:
|
|
||||||
// Timer2 (is different)
|
|
||||||
TCCR2A = (TCCR2A & B11111100) | B00000011; // set WGM0=1 and WGM1=1 for fast PWM
|
|
||||||
TCCR2B = (TCCR2B & B11110000) | B00000001; // set WGM2=0 and prescaler div=1 (max)
|
|
||||||
DIAG(F("2 A=%x B=%x"), TCCR2A, TCCR2B);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
case 7:
|
|
||||||
case 8:
|
|
||||||
// Timer4
|
|
||||||
TCCR4A = (TCCR4A & B11111100) | B00000001; // set WGM0=1 and WGM1=0 for fast PWM 8-bit
|
|
||||||
TCCR4B = (TCCR4B & B11100000) | B00001001; // set WGM2=1 and WGM3=0 for fast PWM 8 bit and div=1 (max)
|
|
||||||
break;
|
|
||||||
case 46:
|
|
||||||
case 45:
|
|
||||||
case 44:
|
|
||||||
// Timer5
|
|
||||||
TCCR5A = (TCCR5A & B11111100) | B00000001; // set WGM0=1 and WGM1=0 for fast PWM 8-bit
|
|
||||||
TCCR5B = (TCCR5B & B11100000) | B00001001; // set WGM2=1 and WGM3=0 for fast PWM 8 bit and div=1 (max)
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
analogWrite(brakePin,duty);
|
analogWrite(brakePin,duty);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user