Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f125095
commit aa0a943
Showing
24 changed files
with
3,759 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
/********************************************************************** | ||
Accessories.cpp | ||
COPYRIGHT (c) 2013-2015 Gregg E. Berman | ||
Part of DCC++ BASE STATION for the Arduino | ||
**********************************************************************/ | ||
/********************************************************************** | ||
DCC++ BASE STATION can keep track of the direction of any turnout that is controlled | ||
by a DCC stationary accessory decoder. All turnouts, as well as any other DCC accessories | ||
connected in this fashion, can always be operated using the DCC BASE STATION Accessory command: | ||
<a ADDRESS SUBADDRESS ACTIVATE> | ||
However, this general command simply sends the appropriate DCC instruction packet to the main tracks | ||
to operate connected accessories. It does not store or retain any information regarding the current | ||
status of that accessory. | ||
To have this sketch store and retain the direction of DCC-connected turnouts, as well as automatically | ||
invoke the required <a> command as needed, first define/edit/delete such turnouts using the following | ||
variations of the "T" command: | ||
<T ID ADDRESS SUBADDRESS>: creates a new turnout ID, with specified ADDRESS and SUBADDRESS | ||
if turnout ID already exists, it is updated with specificed ADDRESS and SUBADDRESS | ||
returns: <O> if successful and <X> if unsuccessful (e.g. out of memory) | ||
<T ID>: deletes definition of turnout ID | ||
returns: <O> if successful and <X> if unsuccessful (e.g. ID does not exist) | ||
<T>: lists all defined turnouts | ||
returns: <H ID ADDRESS SUBADDRESS THROW> for each defined turnout or <X> if no turnouts defined | ||
where | ||
ID: the numeric ID (0-32767) of the turnout to control | ||
ADDRESS: the primary address of the decoder controlling this turnout (0-511) | ||
SUBADDRESS: the subaddress of the decoder controlling this turnout (0-3) | ||
Once all turnouts have been properly defined, use the <E> command to store their definitions to EEPROM. | ||
If you later make edits/additions/deletions to the turnout definitions, you must invoke the <E> command if you want those | ||
new definitions updated in the EEPROM. You can also clear everything stored in the EEPROM by invoking the <e> command. | ||
To "throw" turnouts that have been defined use: | ||
<T ID THROW>: sets turnout ID to either the "thrown" or "unthrown" position | ||
returns: <H ID THROW>, or <X> if turnout ID does not exist | ||
where | ||
ID: the numeric ID (0-32767) of the turnout to control | ||
THROW: 0 (unthrown) or 1 (thrown) | ||
When controlled as such, the Arduino updates and stores the direction of each Turnout in EEPROM so | ||
that it is retained even without power. A list of the current directions of each Turnout in the form <H ID THROW> is generated | ||
by this sketch whenever the <s> status command is invoked. This provides an efficient way of initializing | ||
the directions of any Turnouts being monitored or controlled by a separate interface or GUI program. | ||
**********************************************************************/ | ||
|
||
#include "Accessories.h" | ||
#include "SerialCommand.h" | ||
#include "DCCpp_Uno.h" | ||
#include "EEStore.h" | ||
#include <EEPROM.h> | ||
#include "Comm.h" | ||
|
||
/////////////////////////////////////////////////////////////////////////////// | ||
|
||
void Turnout::activate(int s){ | ||
char c[20]; | ||
data.tStatus=(s>0); // if s>0 set turnout=ON, else if zero or negative set turnout=OFF | ||
sprintf(c,"a %d %d %d",data.address,data.subAddress,data.tStatus); | ||
SerialCommand::parse(c); | ||
if(num>0) | ||
EEPROM.put(num,data.tStatus); | ||
INTERFACE.print("<H"); | ||
INTERFACE.print(data.id); | ||
if(data.tStatus==0) | ||
INTERFACE.print(" 0>"); | ||
else | ||
INTERFACE.print(" 1>"); | ||
} | ||
|
||
/////////////////////////////////////////////////////////////////////////////// | ||
|
||
Turnout* Turnout::get(int n){ | ||
Turnout *tt; | ||
for(tt=firstTurnout;tt!=NULL && tt->data.id!=n;tt=tt->nextTurnout); | ||
return(tt); | ||
} | ||
/////////////////////////////////////////////////////////////////////////////// | ||
|
||
void Turnout::remove(int n){ | ||
Turnout *tt,*pp; | ||
|
||
for(tt=firstTurnout;tt!=NULL && tt->data.id!=n;pp=tt,tt=tt->nextTurnout); | ||
|
||
if(tt==NULL){ | ||
INTERFACE.print("<X>"); | ||
return; | ||
} | ||
|
||
if(tt==firstTurnout) | ||
firstTurnout=tt->nextTurnout; | ||
else | ||
pp->nextTurnout=tt->nextTurnout; | ||
|
||
free(tt); | ||
|
||
INTERFACE.print("<O>"); | ||
} | ||
|
||
/////////////////////////////////////////////////////////////////////////////// | ||
|
||
void Turnout::show(int n){ | ||
Turnout *tt; | ||
|
||
if(firstTurnout==NULL){ | ||
INTERFACE.print("<X>"); | ||
return; | ||
} | ||
|
||
for(tt=firstTurnout;tt!=NULL;tt=tt->nextTurnout){ | ||
INTERFACE.print("<H"); | ||
INTERFACE.print(tt->data.id); | ||
if(n==1){ | ||
INTERFACE.print(" "); | ||
INTERFACE.print(tt->data.address); | ||
INTERFACE.print(" "); | ||
INTERFACE.print(tt->data.subAddress); | ||
} | ||
if(tt->data.tStatus==0) | ||
INTERFACE.print(" 0>"); | ||
else | ||
INTERFACE.print(" 1>"); | ||
} | ||
} | ||
|
||
/////////////////////////////////////////////////////////////////////////////// | ||
|
||
void Turnout::parse(char *c){ | ||
int n,s,m; | ||
Turnout *t; | ||
|
||
switch(sscanf(c,"%d %d %d",&n,&s,&m)){ | ||
|
||
case 2: // argument is string with id number of turnout followed by zero (not thrown) or one (thrown) | ||
t=get(n); | ||
if(t!=NULL) | ||
t->activate(s); | ||
else | ||
INTERFACE.print("<X>"); | ||
break; | ||
|
||
case 3: // argument is string with id number of turnout followed by an address and subAddress | ||
create(n,s,m,1); | ||
break; | ||
|
||
case 1: // argument is a string with id number only | ||
remove(n); | ||
break; | ||
|
||
case -1: // no arguments | ||
show(1); // verbose show | ||
break; | ||
} | ||
} | ||
|
||
/////////////////////////////////////////////////////////////////////////////// | ||
|
||
void Turnout::load(){ | ||
struct TurnoutData data; | ||
Turnout *tt; | ||
|
||
for(int i=0;i<EEStore::eeStore->data.nTurnouts;i++){ | ||
EEPROM.get(EEStore::pointer(),data); | ||
tt=create(data.id,data.address,data.subAddress); | ||
tt->data.tStatus=data.tStatus; | ||
tt->num=EEStore::pointer(); | ||
EEStore::advance(sizeof(tt->data)); | ||
} | ||
} | ||
|
||
/////////////////////////////////////////////////////////////////////////////// | ||
|
||
void Turnout::store(){ | ||
Turnout *tt; | ||
|
||
tt=firstTurnout; | ||
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; | ||
EEStore::eeStore->data.nTurnouts++; | ||
} | ||
|
||
} | ||
/////////////////////////////////////////////////////////////////////////////// | ||
|
||
Turnout *Turnout::create(int id, int add, int subAdd, int v){ | ||
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){ // problem allocating memory | ||
if(v==1) | ||
INTERFACE.print("<X>"); | ||
return(tt); | ||
} | ||
|
||
tt->data.id=id; | ||
tt->data.address=add; | ||
tt->data.subAddress=subAdd; | ||
tt->data.tStatus=0; | ||
if(v==1) | ||
INTERFACE.print("<O>"); | ||
return(tt); | ||
|
||
} | ||
|
||
/////////////////////////////////////////////////////////////////////////////// | ||
|
||
Turnout *Turnout::firstTurnout=NULL; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/********************************************************************** | ||
Accessories.h | ||
COPYRIGHT (c) 2013-2015 Gregg E. Berman | ||
Part of DCC++ BASE STATION for the Arduino | ||
**********************************************************************/ | ||
|
||
#include "Arduino.h" | ||
|
||
#ifndef Accessories_h | ||
#define Accessories_h | ||
|
||
struct TurnoutData { | ||
byte tStatus; | ||
byte subAddress; | ||
int id; | ||
int address; | ||
}; | ||
|
||
struct Turnout{ | ||
static Turnout *firstTurnout; | ||
int num; | ||
struct TurnoutData data; | ||
Turnout *nextTurnout; | ||
void activate(int s); | ||
static void parse(char *c); | ||
static Turnout* get(int); | ||
static void remove(int); | ||
static void load(); | ||
static void store(); | ||
static Turnout *create(int, int, int, int=0); | ||
static void show(int=0); | ||
}; // Turnout | ||
|
||
#endif | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/********************************************************************** | ||
Comm.h | ||
COPYRIGHT (c) 2013-2015 Gregg E. Berman | ||
Part of DCC++ BASE STATION for the Arduino | ||
**********************************************************************/ | ||
|
||
#if COMM_TYPE == 1 | ||
#include ETHERNET_LIBRARY | ||
extern EthernetServer INTERFACE; | ||
#endif | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/********************************************************************** | ||
Config.h | ||
COPYRIGHT (c) 2013-2015 Gregg E. Berman | ||
Part of DCC++ BASE STATION for the Arduino | ||
**********************************************************************/ | ||
|
||
///////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// DEFINE MOTOR_SHIELD_TYPE ACCORDING TO THE FOLLOWING TABLE: | ||
// | ||
// 0 = ARDUINO MOTOR SHIELD (MAX 18V/2A PER CHANNEL) | ||
// 1 = POLOLU MC33926 MOTOR SHIELD (MAX 28V/3A PER CHANNEL) | ||
|
||
#define MOTOR_SHIELD_TYPE 0 | ||
|
||
///////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// DEFINE NUMBER OF MAIN TRACK REGISTER | ||
|
||
#define MAX_MAIN_REGISTERS 12 | ||
|
||
///////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// DEFINE COMMUNICATIONS INTERFACE TYPE | ||
// | ||
// 0 = Built-in Serial Port | ||
// 1 = Arduino Ethernet/SD Card Shield | ||
|
||
#define COMM_TYPE 0 | ||
|
||
///////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// DEFINE NAME OF ETHERNET LIBRARY TO INCLUDE (DIFFERENT SHIELDS MAY USE THEIR OWN LIBRARIES) | ||
|
||
//#define ETHERNET_LIBRARY <EthernetV2_0.h> // https://github.com/Seeed-Studio/Ethernet_Shield_W5200 | ||
#define ETHERNET_LIBRARY <Ethernet2.h> // https://github.com/arduino-org/Arduino | ||
|
||
///////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// DEFINE PORT TO USE FOR ETHERNET COMMUNICATIONS INTERFACE | ||
// | ||
|
||
#define ETHERNET_PORT 2560 | ||
|
||
///////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// DEFINE MAC ADDRESS ARRAY FOR ETHERNET COMMUNICATIONS INTERFACE | ||
// | ||
|
||
#define MAC_ADDRESS { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF } | ||
|
||
///////////////////////////////////////////////////////////////////////////////////// | ||
|
Oops, something went wrong.