1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-12-23 21:01:25 +01:00

Drop railcom and prepare for servo turnouts

This commit is contained in:
Asbelos 2020-06-23 17:43:50 +01:00
parent 7c68a9de70
commit e7e4d4fbd9
10 changed files with 87 additions and 90 deletions

View File

@ -44,10 +44,15 @@ void myCallback(int result) {
}
// Create a serkial command parser... This is OPTIONAL if you don't need to handle JMRI type commands
// Create a serial command parser... This is OPTIONAL if you don't need to handle JMRI type commands
// from the Serial port.
DCCEXParser serialParser;
// Try monitoring the memory
#include "freeMemory.h"
int minMemory;
void setup() {
Serial.begin(SERIAL_BAUD_RATE);
DCC::begin();
@ -59,8 +64,11 @@ void setup() {
// Optionally tell parser to use my example filter
DCCEXParser::setFilter(myFilter);
malloc(1);
minMemory=freeMemory();
DIAG(F("\nFree memory=%d"),minMemory);
DIAG(F("\nReady for JMRI commands\n"));
}
void loop() {
@ -71,4 +79,11 @@ void loop() {
// This line passes input on Wifi to another DCCEXParser
if (WIFI_PORT>0) WifiInterface::loop();
// Report any decrease in memory
int freeNow=freeMemory();
if (freeNow<minMemory) {
minMemory=freeNow;
DIAG(F("\nFree memory=%d"),minMemory);
}
}

View File

@ -2,7 +2,7 @@
#include "Hardware.h"
#include "DCCWaveform.h"
#include "DIAG.h"
#include "Railcom.h"
DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true);
DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false);
@ -116,7 +116,6 @@ bool DCCWaveform::interrupt1() {
switch (state) {
case 0: // start of bit transmission
Hardware::setSignal(isMainTrack, HIGH);
checkRailcom();
state = 1;
return true; // must call interrupt2 to set currentBit
@ -190,14 +189,7 @@ void DCCWaveform::interrupt2() {
}
}
void DCCWaveform::checkRailcom() {
if (isMainTrack && RAILCOM_CUTOUT) {
byte preamble = PREAMBLE_BITS_MAIN - remainingPreambles;
if (preamble == RAILCOM_PREAMBLES_BEFORE_CUTOUT) {
Railcom::startCutout();
}
}
}
// Wait until there is no packet pending, then make this pending
void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repeats) {

View File

@ -16,10 +16,6 @@ const int ACK_MIN_PULSE = 60 ; // current above baseline which a pulse is re
const int PREAMBLE_BITS_MAIN = 20;
const int PREAMBLE_BITS_PROG = 22;
// Railcom settings
const bool RAILCOM_CUTOUT = true;
const byte RAILCOM_PREAMBLES_BEFORE_CUTOUT = 1; // how far into the preamble do we cutout
const byte MAX_PACKET_SIZE = 12;
@ -68,7 +64,6 @@ class DCCWaveform {
byte bits_sent; // 0-8 (yes 9 bits) sent for current byte
byte bytes_sent; // number of bytes sent from transmitPacket
byte state; // wave generator state machine
void checkRailcom();
byte pendingPacket[MAX_PACKET_SIZE];
byte pendingLength;

View File

@ -52,6 +52,11 @@ void Hardware::setCallback(int duration, void (*isr)()) {
Timer1.attachInterrupt(isr);
}
void Hardware::setServo(byte pin, int angle) {
// TBD
}
// Railcom support functions, not yet implemented
void Hardware::setSingleCallback(int duration, void (*isr)()) {
// Timer2.initialize(duration);

View File

@ -11,5 +11,6 @@ class Hardware {
static void setCallback(int duration, void (*isr)());
static void setSingleCallback(int duration, void (*isr)());
static void resetSingleCallback(int duration);
static void setServo(byte pin, int angle);
};
#endif

View File

@ -1,25 +0,0 @@
#include "Railcom.h"
#include "Hardware.h"
void Railcom::startCutout() {
return;
/*** todo when ready ***
interruptState=0;
Hardware::setSingleCallback(RAILCOM_T0,interrupt);
*************/
}
void Railcom::interrupt() {
/*** TODO when ready .. railcom state machine
switch (interruptState) {
case 0: //
Hardware::setPower(true,false);
state=1;
nextInterrupt=RAILCOM_T1;
break;
}
**********************/
}
byte Railcom::interruptState;
byte Railcom::bitsReceived;
byte Railcom::buffer[MAX_BUFFER];

View File

@ -1,16 +0,0 @@
#ifndef Railcom_h
#define Railcom_h
#include <Arduino.h>
class Railcom {
public:
static void startCutout();
static void interrupt();
private:
static byte interruptState;
static byte bitsReceived;
static const byte MAX_BUFFER=20;
static byte buffer[MAX_BUFFER];
};
#endif

View File

@ -1,7 +1,7 @@
#include "Turnouts.h"
#include "EEStore.h"
#include "StringFormatter.h"
#include "Hardware.h"
bool Turnout::activate(int n,bool state){
Turnout * tt=get(n);
if (tt==NULL) return false;
@ -12,8 +12,10 @@
// activate is virtual here so that it can be overridden by a non-DCC turnout mechanism
void Turnout::activate(bool state) {
data.tStatus=state;
DCC::setAccessory(data.address,data.subAddress, data.tStatus);
if (state) data.tStatus|=STATUS_ACTIVE;
else data.tStatus &= ~STATUS_ACTIVE;
if (data.tStatus & STATUS_PWM) Hardware::setServo(data.tStatus & STATUS_PWMPIN, (data.inactiveAngle+state?data.moveAngle:0));
else DCC::setAccessory(data.address,data.subAddress, state);
}
///////////////////////////////////////////////////////////////////////////////
@ -46,7 +48,7 @@ bool Turnout::remove(int n){
void Turnout::show(Print & stream, int n){
for(Turnout *tt=firstTurnout;tt!=NULL;tt=tt->nextTurnout){
if (tt->data.id==n) {
StringFormatter::send(stream,F("<H %d %d>"), tt->data.id, tt->data.tStatus);
StringFormatter::send(stream,F("<H %d %d>"), tt->data.id, tt->data.tStatus & STATUS_ACTIVE);
return;
}
}
@ -70,9 +72,9 @@ void Turnout::load(){
for(int i=0;i<EEStore::eeStore->data.nTurnouts;i++){
EEPROM.get(EEStore::pointer(),data);
tt=create(data.id,data.address,data.subAddress);
if (data.tStatus & STATUS_PWM) tt=create(data.id,data.tStatus & STATUS_PWMPIN, data.inactiveAngle,data.moveAngle);
else tt=create(data.id,data.address,data.subAddress);
tt->data.tStatus=data.tStatus;
tt->num=EEStore::pointer();
EEStore::advance(sizeof(tt->data));
}
}
@ -86,7 +88,6 @@ void Turnout::store(){
EEStore::eeStore->data.nTurnouts=0;
while(tt!=NULL){
tt->num=EEStore::pointer();
EEPROM.put(EEStore::pointer(),tt->data);
EEStore::advance(sizeof(tt->data));
tt=tt->nextTurnout;
@ -97,29 +98,31 @@ void Turnout::store(){
///////////////////////////////////////////////////////////////////////////////
Turnout *Turnout::create(int id, int add, int subAdd){
Turnout *tt;
if(firstTurnout==NULL){
firstTurnout=(Turnout *)calloc(1,sizeof(Turnout));
tt=firstTurnout;
} else if((tt=get(id))==NULL){
tt=firstTurnout;
while(tt->nextTurnout!=NULL)
tt=tt->nextTurnout;
tt->nextTurnout=(Turnout *)calloc(1,sizeof(Turnout));
tt=tt->nextTurnout;
}
if (tt==NULL) return(tt);
tt->data.id=id;
Turnout *tt=create(id);
tt->data.address=add;
tt->data.subAddress=subAdd;
tt->data.tStatus=0;
return(tt);
}
///////////////////////////////////////////////////////////////////////////////
Turnout *Turnout::create(int id, byte pin, int activeAngle, int inactiveAngle){
Turnout *tt=create(id);
tt->data.tStatus= STATUS_PWM | (pin & STATUS_PWMPIN);
tt->data.inactiveAngle=inactiveAngle;
tt->data.moveAngle=activeAngle-inactiveAngle;
return(tt);
}
Turnout *Turnout::create(int id){
Turnout *tt=get(id);
if (tt==NULL) {
tt=(Turnout *)calloc(1,sizeof(Turnout));
tt->nextTurnout=firstTurnout;
firstTurnout=tt;
tt->data.id=id;
}
return tt;
}
///////////////////////////////////////////////////////////////////////////////
Turnout *Turnout::firstTurnout=NULL;

View File

@ -4,24 +4,29 @@
#include <Arduino.h>
#include "DCC.h"
const byte STATUS_ACTIVE=0x80; // Flag as activated
const byte STATUS_PWM=0x40; // Flag as a PWM turnout
const byte STATUS_PWMPIN=0x3F; // PWM pin 0-63
struct TurnoutData {
uint8_t tStatus;
uint8_t subAddress;
int id;
int address;
int id;
uint8_t tStatus; // has STATUS_ACTIVE, STATUS_PWM, STATUS_PWMPIN
union {uint8_t subAddress; char moveAngle;}; //DCC sub addrerss or PWM difference from inactiveAngle
union {int address; int inactiveAngle;}; // DCC address or PWM servo angle
};
struct Turnout{
static Turnout *firstTurnout;
int num;
struct TurnoutData data;
TurnoutData data;
Turnout *nextTurnout;
static bool activate(int n, bool state);
static Turnout* get(int);
static bool remove(int);
static void load();
static void store();
static Turnout *create(int, int, int);
static Turnout *create(int id , int address , int subAddress);
static Turnout *create(int id , byte pin , int activeAngle, int inactiveAngle);
static Turnout *create(int id);
static void show(Print & stream, int n);
static bool showAll(Print & stream);
virtual void activate(bool state);

22
freeMemory.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef freeMemory_h
#define freeMemory_h
// thanks go to https://github.com/mpflaga/Arduino-MemoryFree
#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else // __ARM__
extern char *__brkval;
#endif // __arm__
int freeMemory() {
char top;
#ifdef __arm__
return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
return &top - __brkval;
#else // __arm__
return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif // __arm__
}
#endif