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:
parent
7c68a9de70
commit
e7e4d4fbd9
17
CVReader.ino
17
CVReader.ino
@ -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,6 +64,9 @@ 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"));
|
||||
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
25
Railcom.cpp
25
Railcom.cpp
@ -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];
|
16
Railcom.h
16
Railcom.h
@ -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
|
53
Turnouts.cpp
53
Turnouts.cpp
@ -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;
|
||||
|
17
Turnouts.h
17
Turnouts.h
@ -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;
|
||||
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
22
freeMemory.h
Normal 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
|
Loading…
Reference in New Issue
Block a user