mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-12-25 21:41:23 +01:00
Merge remote-tracking branch 'origin/master' into dex/unowifi
This commit is contained in:
commit
e7c76bf806
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1,2 +1,3 @@
|
|||||||
# Auto detect text files and perform LF normalization
|
# Auto detect text files and perform LF normalization
|
||||||
* text=auto
|
* text=auto
|
||||||
|
*.svg -text
|
||||||
|
62
CONTRIBUTING.md
Normal file
62
CONTRIBUTING.md
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# Contributing
|
||||||
|
|
||||||
|
Thanks for considering contributing to our project. Here is a guide for how to get started and and a list of our conventions. We will also walk you through the Github command line and Desktop commands necessary to download the code, make changes, and get it included in a next version of the sofware.
|
||||||
|
|
||||||
|
Before contributing to this repository, please first discuss the change you wish to make via issue, or any other method with the owners of this repository before making a change.
|
||||||
|
|
||||||
|
Find us on our website at https://dcc-ex.com, on our Discord https://discord.gg/y2sB4Fp or on Trainboard: https://www.trainboard.com/highball/index.php?threads/dcc-update-project-2020.130071/
|
||||||
|
|
||||||
|
# Development Environment
|
||||||
|
|
||||||
|
We recommend using PlatformIO IDE for VSCode. If you haven't yet used it, it is an easy to learn and easy to use IDE that really shines for embedded development and the Arduino based hardware we use. For more information go to https://platformio.org/
|
||||||
|
|
||||||
|
* Download and install the latest version of the Arduino IDE
|
||||||
|
* Download and install the latest version of Visual Studio Code from Microsoft
|
||||||
|
* Run VSCode and click on the "extensions" icon on the left. Install "PlatformIO IDE for VSCode" and the "Arduino Framework" support
|
||||||
|
|
||||||
|
If you don't see C/C++ Installed in the list, install that too. We also recomment installing the Gitlens extension to make working with Git and GitHub even easier.
|
||||||
|
|
||||||
|
You may ask if you can use the Arduino IDE, Visual Studio, or even a text editor and the answer is "of course" if you know what you are doing. Since you are just changing text files, you can use whatever you like as long as your commits and pull requests can be merged in GitHub. However, it will be much easier to follow our coding standards if you have an IDE that can automatically format things for you.
|
||||||
|
|
||||||
|
# Coding Style Guidelines
|
||||||
|
|
||||||
|
We have adopted the Google style guidlines. In particular please make sure to adhere to these standards:
|
||||||
|
|
||||||
|
1. All header files should have #define guards to prevent multiple inclusion.
|
||||||
|
2. Use Unix style line endings
|
||||||
|
3. We indent using two spaces (soft tabs)
|
||||||
|
4. Braces
|
||||||
|
|
||||||
|
For more information just check our code or read https://google.github.io/styleguide/cppguide.html#C++_Version
|
||||||
|
|
||||||
|
## Using the Repository
|
||||||
|
|
||||||
|
1. Clone the repository on your local machine
|
||||||
|
2. Create a working branch using the format "username-featurename" ex: "git branch -b frightrisk-turnouts"
|
||||||
|
3. Commit offen, ex: "git add ." and then "git commit -m "description of your changes"
|
||||||
|
4. Push your changes to our repository "git push"
|
||||||
|
5. When you are ready, issue a pull request for your changes to be merged into the main branch
|
||||||
|
|
||||||
|
## Pull Request Process
|
||||||
|
|
||||||
|
1. Ensure any install or build dependencies are removed before the end of the layer when doing a build.
|
||||||
|
|
||||||
|
## Code of Conduct
|
||||||
|
|
||||||
|
Be Nice
|
||||||
|
|
||||||
|
### Enforcement
|
||||||
|
|
||||||
|
Contributors who do not follow the be nice rule in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||||
|
|
||||||
|
## How Can I Contribute?
|
||||||
|
|
||||||
|
The DCC-EX Team has several projects and sub teams where you can help donate your epertise. See the sections below for the project or projects you are interested in.
|
||||||
|
|
||||||
|
### Development
|
||||||
|
### Documentation
|
||||||
|
### WebThrottle-EX
|
||||||
|
### Web Support
|
||||||
|
### Organization/Coordination
|
||||||
|
|
||||||
|
Links to external documentation goes here XXX
|
2
DCCEX.h
2
DCCEX.h
@ -10,7 +10,9 @@
|
|||||||
#include "DCCEXParser.h"
|
#include "DCCEXParser.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "WifiInterface.h"
|
#include "WifiInterface.h"
|
||||||
|
#if ETHERNET_ON == true
|
||||||
#include "EthernetInterface.h"
|
#include "EthernetInterface.h"
|
||||||
|
#endif
|
||||||
#include "LCD_Implementation.h"
|
#include "LCD_Implementation.h"
|
||||||
#include "freeMemory.h"
|
#include "freeMemory.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
112
DCCEXParser.cpp
112
DCCEXParser.cpp
@ -49,6 +49,8 @@ const int HASH_KEYWORD_PROGBOOST = -6353;
|
|||||||
const int HASH_KEYWORD_EEPROM = -7168;
|
const int HASH_KEYWORD_EEPROM = -7168;
|
||||||
const int HASH_KEYWORD_LIMIT = 27413;
|
const int HASH_KEYWORD_LIMIT = 27413;
|
||||||
const int HASH_KEYWORD_ETHERNET = -30767;
|
const int HASH_KEYWORD_ETHERNET = -30767;
|
||||||
|
const int HASH_KEYWORD_MAX = 16244;
|
||||||
|
const int HASH_KEYWORD_MIN = 15978;
|
||||||
|
|
||||||
int DCCEXParser::stashP[MAX_PARAMS];
|
int DCCEXParser::stashP[MAX_PARAMS];
|
||||||
bool DCCEXParser::stashBusy;
|
bool DCCEXParser::stashBusy;
|
||||||
@ -158,6 +160,66 @@ int DCCEXParser::splitValues(int result[MAX_PARAMS], const byte *cmd)
|
|||||||
return parameterCount;
|
return parameterCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DCCEXParser::splitHexValues(int result[MAX_PARAMS], const byte *cmd)
|
||||||
|
{
|
||||||
|
byte state = 1;
|
||||||
|
byte parameterCount = 0;
|
||||||
|
int runningValue = 0;
|
||||||
|
const byte *remainingCmd = cmd + 1; // skips the opcode
|
||||||
|
|
||||||
|
// clear all parameters in case not enough found
|
||||||
|
for (int i = 0; i < MAX_PARAMS; i++)
|
||||||
|
result[i] = 0;
|
||||||
|
|
||||||
|
while (parameterCount < MAX_PARAMS)
|
||||||
|
{
|
||||||
|
byte hot = *remainingCmd;
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
|
||||||
|
case 1: // skipping spaces before a param
|
||||||
|
if (hot == ' ')
|
||||||
|
break;
|
||||||
|
if (hot == '\0' || hot == '>')
|
||||||
|
return parameterCount;
|
||||||
|
state = 2;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 2: // checking first hex digit
|
||||||
|
runningValue = 0;
|
||||||
|
state = 3;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 3: // building a parameter
|
||||||
|
if (hot >= '0' && hot <= '9')
|
||||||
|
{
|
||||||
|
runningValue = 16 * runningValue + (hot - '0');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (hot >= 'A' && hot <= 'F')
|
||||||
|
{
|
||||||
|
runningValue = 16 * runningValue + 10 + (hot - 'A');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (hot >= 'a' && hot <= 'f')
|
||||||
|
{
|
||||||
|
runningValue = 16 * runningValue + 10 + (hot - 'a');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (hot==' ' || hot=='>' || hot=='\0') {
|
||||||
|
result[parameterCount] = runningValue;
|
||||||
|
parameterCount++;
|
||||||
|
state = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return -1; // invalid hex digit
|
||||||
|
}
|
||||||
|
remainingCmd++;
|
||||||
|
}
|
||||||
|
return parameterCount;
|
||||||
|
}
|
||||||
|
|
||||||
FILTER_CALLBACK DCCEXParser::filterCallback = 0;
|
FILTER_CALLBACK DCCEXParser::filterCallback = 0;
|
||||||
AT_COMMAND_CALLBACK DCCEXParser::atCommandCallback = 0;
|
AT_COMMAND_CALLBACK DCCEXParser::atCommandCallback = 0;
|
||||||
void DCCEXParser::setFilter(FILTER_CALLBACK filter)
|
void DCCEXParser::setFilter(FILTER_CALLBACK filter)
|
||||||
@ -210,7 +272,8 @@ void DCCEXParser::parse(Print *stream, byte *com, bool blocking)
|
|||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Convert JMRI bizarre -1=emergency stop, 0-126 as speeds
|
// Convert DCC-EX protocol speed steps where
|
||||||
|
// -1=emergency stop, 0-126 as speeds
|
||||||
// to DCC 0=stop, 1= emergency stop, 2-127 speeds
|
// to DCC 0=stop, 1= emergency stop, 2-127 speeds
|
||||||
if (tspeed > 126 || tspeed < -1)
|
if (tspeed > 126 || tspeed < -1)
|
||||||
break; // invalid JMRI speed code
|
break; // invalid JMRI speed code
|
||||||
@ -265,6 +328,21 @@ void DCCEXParser::parse(Print *stream, byte *com, bool blocking)
|
|||||||
DCC::writeCVBitMain(p[0], p[1], p[2], p[3]);
|
DCC::writeCVBitMain(p[0], p[1], p[2], p[3]);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case 'M': // WRITE TRANSPARENT DCC PACKET MAIN <M REG X1 ... X9>
|
||||||
|
case 'P': // WRITE TRANSPARENT DCC PACKET PROG <P REG X1 ... X9>
|
||||||
|
// Re-parse the command using a hex-only splitter
|
||||||
|
params=splitHexValues(p,com)-1; // drop REG
|
||||||
|
if (params<1) break;
|
||||||
|
{
|
||||||
|
byte packet[params];
|
||||||
|
for (int i=0;i<params;i++) {
|
||||||
|
packet[i]=(byte)p[i+1];
|
||||||
|
if (Diag::CMD) DIAG(F("packet[%d]=%d (0x%x)\n"), i, packet[i], packet[i]);
|
||||||
|
}
|
||||||
|
(opcode=='M'?DCCWaveform::mainTrack:DCCWaveform::progTrack).schedulePacket(packet,params,3);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
case 'W': // WRITE CV ON PROG <W CV VALUE CALLBACKNUM CALLBACKSUB>
|
case 'W': // WRITE CV ON PROG <W CV VALUE CALLBACKNUM CALLBACKSUB>
|
||||||
if (!stashCallback(stream, p))
|
if (!stashCallback(stream, p))
|
||||||
break;
|
break;
|
||||||
@ -357,7 +435,7 @@ void DCCEXParser::parse(Print *stream, byte *com, bool blocking)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 'c': // READ CURRENT <c>
|
case 'c': // READ CURRENT <c>
|
||||||
StringFormatter::send(stream, F("<a %d>"), DCCWaveform::mainTrack.getLastCurrent());
|
StringFormatter::send(stream, F("<a %d>"), DCCWaveform::mainTrack.get1024Current());
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 'Q': // SENSORS <Q>
|
case 'Q': // SENSORS <Q>
|
||||||
@ -367,8 +445,10 @@ void DCCEXParser::parse(Print *stream, byte *com, bool blocking)
|
|||||||
case 's': // <s>
|
case 's': // <s>
|
||||||
StringFormatter::send(stream, F("<p%d>"), DCCWaveform::mainTrack.getPowerMode() == POWERMODE::ON);
|
StringFormatter::send(stream, F("<p%d>"), DCCWaveform::mainTrack.getPowerMode() == POWERMODE::ON);
|
||||||
StringFormatter::send(stream, F("<iDCC-EX V-%S / %S / %S G-%S>"), F(VERSION), F(ARDUINO_TYPE), DCC::getMotorShieldName(), F(GITHUB_SHA));
|
StringFormatter::send(stream, F("<iDCC-EX V-%S / %S / %S G-%S>"), F(VERSION), F(ARDUINO_TYPE), DCC::getMotorShieldName(), F(GITHUB_SHA));
|
||||||
|
parseT(stream, 0, p); //send all Turnout states
|
||||||
|
Output::printAll(stream); //send all Output states
|
||||||
|
Sensor::printAll(stream); //send all Sensor states
|
||||||
// TODO Send stats of speed reminders table
|
// TODO Send stats of speed reminders table
|
||||||
// TODO send status of turnouts etc etc
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 'E': // STORE EPROM <E>
|
case 'E': // STORE EPROM <E>
|
||||||
@ -402,6 +482,8 @@ void DCCEXParser::parse(Print *stream, byte *com, bool blocking)
|
|||||||
|
|
||||||
case '+': // Complex Wifi interface command (not usual parse)
|
case '+': // Complex Wifi interface command (not usual parse)
|
||||||
if (atCommandCallback) {
|
if (atCommandCallback) {
|
||||||
|
DCCWaveform::mainTrack.setPowerMode(POWERMODE::OFF);
|
||||||
|
DCCWaveform::progTrack.setPowerMode(POWERMODE::OFF);
|
||||||
atCommandCallback(com);
|
atCommandCallback(com);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -509,7 +591,7 @@ bool DCCEXParser::parseT(Print *stream, int params, int p[])
|
|||||||
{
|
{
|
||||||
switch (params)
|
switch (params)
|
||||||
{
|
{
|
||||||
case 0: // <T> show all turnouts
|
case 0: // <T> list all turnout states
|
||||||
{
|
{
|
||||||
bool gotOne = false;
|
bool gotOne = false;
|
||||||
for (Turnout *tt = Turnout::firstTurnout; tt != NULL; tt = tt->nextTurnout)
|
for (Turnout *tt = Turnout::firstTurnout; tt != NULL; tt = tt->nextTurnout)
|
||||||
@ -564,7 +646,7 @@ bool DCCEXParser::parseS(Print *stream, int params, int p[])
|
|||||||
StringFormatter::send(stream, F("<O>"));
|
StringFormatter::send(stream, F("<O>"));
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case 0: // <S> lit sensor states
|
case 0: // <S> list sensor states
|
||||||
if (Sensor::firstSensor == NULL)
|
if (Sensor::firstSensor == NULL)
|
||||||
return false;
|
return false;
|
||||||
for (Sensor *tt = Sensor::firstSensor; tt != NULL; tt = tt->nextSensor)
|
for (Sensor *tt = Sensor::firstSensor; tt != NULL; tt = tt->nextSensor)
|
||||||
@ -594,12 +676,22 @@ bool DCCEXParser::parseD(Print *stream, int params, int p[])
|
|||||||
StringFormatter::send(stream, F("\nFree memory=%d\n"), freeMemory());
|
StringFormatter::send(stream, F("\nFree memory=%d\n"), freeMemory());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HASH_KEYWORD_ACK: // <D ACK ON/OFF>
|
case HASH_KEYWORD_ACK: // <D ACK ON/OFF> <D ACK [LIMIT|MIN|MAX] Value>
|
||||||
if (params >= 2 && p[1] == HASH_KEYWORD_LIMIT) {
|
if (params >= 3) {
|
||||||
|
if (p[1] == HASH_KEYWORD_LIMIT) {
|
||||||
DCCWaveform::progTrack.setAckLimit(p[2]);
|
DCCWaveform::progTrack.setAckLimit(p[2]);
|
||||||
StringFormatter::send(stream, F("\nAck limit=%dmA\n"), p[2]);
|
StringFormatter::send(stream, F("\nAck limit=%dmA\n"), p[2]);
|
||||||
} else
|
} else if (p[1] == HASH_KEYWORD_MIN) {
|
||||||
|
DCCWaveform::progTrack.setMinAckPulseDuration(p[2]);
|
||||||
|
StringFormatter::send(stream, F("\nAck min=%dus\n"), p[2]);
|
||||||
|
} else if (p[1] == HASH_KEYWORD_MAX) {
|
||||||
|
DCCWaveform::progTrack.setMaxAckPulseDuration(p[2]);
|
||||||
|
StringFormatter::send(stream, F("\nAck max=%dus\n"), p[2]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
StringFormatter::send(stream, F("\nAck diag %S\n"), onOff ? F("on") : F("off"));
|
||||||
Diag::ACK = onOff;
|
Diag::ACK = onOff;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case HASH_KEYWORD_CMD: // <D CMD ON/OFF>
|
case HASH_KEYWORD_CMD: // <D CMD ON/OFF>
|
||||||
@ -626,8 +718,8 @@ bool DCCEXParser::parseD(Print *stream, int params, int p[])
|
|||||||
DCC::setProgTrackBoost(true);
|
DCC::setProgTrackBoost(true);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case HASH_KEYWORD_EEPROM:
|
case HASH_KEYWORD_EEPROM: // <D EEPROM NumEntries>
|
||||||
if (params >= 1)
|
if (params >= 2)
|
||||||
EEStore::dump(p[1]);
|
EEStore::dump(p[1]);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ struct DCCEXParser
|
|||||||
bool inCommandPayload=false;
|
bool inCommandPayload=false;
|
||||||
byte buffer[MAX_BUFFER+2];
|
byte buffer[MAX_BUFFER+2];
|
||||||
int splitValues( int result[MAX_PARAMS], const byte * command);
|
int splitValues( int result[MAX_PARAMS], const byte * command);
|
||||||
|
int splitHexValues( int result[MAX_PARAMS], const byte * command);
|
||||||
|
|
||||||
bool parseT(Print * stream, int params, int p[]);
|
bool parseT(Print * stream, int params, int p[]);
|
||||||
bool parseZ(Print * stream, int params, int p[]);
|
bool parseZ(Print * stream, int params, int p[]);
|
||||||
|
@ -190,13 +190,17 @@ bool DCCWaveform::interrupt1() {
|
|||||||
setSignal(LOW);
|
setSignal(LOW);
|
||||||
state = 0;
|
state = 0;
|
||||||
}
|
}
|
||||||
else state = 2;
|
else {
|
||||||
|
setSignal(HIGH); // jitter prevention
|
||||||
|
state = 2;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 2: // 116us after case 0
|
case 2: // 116us after case 0
|
||||||
setSignal(LOW);
|
setSignal(LOW);
|
||||||
state = 3;
|
state = 3;
|
||||||
break;
|
break;
|
||||||
case 3: // finished sending zero bit
|
case 3: // finished sending zero bit
|
||||||
|
setSignal(LOW); // jitter prevention
|
||||||
state = 0;
|
state = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -297,9 +301,10 @@ void DCCWaveform::setAckBaseline() {
|
|||||||
if (isMainTrack) return;
|
if (isMainTrack) return;
|
||||||
int baseline = motorDriver->getCurrentRaw();
|
int baseline = motorDriver->getCurrentRaw();
|
||||||
ackThreshold= baseline + motorDriver->mA2raw(ackLimitmA);
|
ackThreshold= baseline + motorDriver->mA2raw(ackLimitmA);
|
||||||
if (Diag::ACK) DIAG(F("\nACK baseline=%d/%dmA threshold=%d/%dmA"),
|
if (Diag::ACK) DIAG(F("\nACK baseline=%d/%dmA Threshold=%d/%dmA Duration: %dus <= pulse <= %dus"),
|
||||||
baseline,motorDriver->raw2mA(baseline),
|
baseline,motorDriver->raw2mA(baseline),
|
||||||
ackThreshold,motorDriver->raw2mA(ackThreshold));
|
ackThreshold,motorDriver->raw2mA(ackThreshold),
|
||||||
|
minAckPulseDuration, maxAckPulseDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCCWaveform::setAckPending() {
|
void DCCWaveform::setAckPending() {
|
||||||
@ -314,7 +319,7 @@ void DCCWaveform::setAckPending() {
|
|||||||
|
|
||||||
byte DCCWaveform::getAck() {
|
byte DCCWaveform::getAck() {
|
||||||
if (ackPending) return (2); // still waiting
|
if (ackPending) return (2); // still waiting
|
||||||
if (Diag::ACK) DIAG(F("\nACK-%S after %dmS max=%d/%dmA pulse=%duS"),ackDetected?F("OK"):F("FAIL"), ackCheckDuration,
|
if (Diag::ACK) DIAG(F("\n%S after %dmS max=%d/%dmA pulse=%duS"),ackDetected?F("ACK"):F("NO-ACK"), ackCheckDuration,
|
||||||
ackMaxCurrent,motorDriver->raw2mA(ackMaxCurrent), ackPulseDuration);
|
ackMaxCurrent,motorDriver->raw2mA(ackMaxCurrent), ackPulseDuration);
|
||||||
if (ackDetected) return (1); // Yes we had an ack
|
if (ackDetected) return (1); // Yes we had an ack
|
||||||
return(0); // pending set off but not detected means no ACK.
|
return(0); // pending set off but not detected means no ACK.
|
||||||
@ -331,7 +336,7 @@ void DCCWaveform::checkAck() {
|
|||||||
|
|
||||||
lastCurrent=motorDriver->getCurrentRaw();
|
lastCurrent=motorDriver->getCurrentRaw();
|
||||||
if (lastCurrent > ackMaxCurrent) ackMaxCurrent=lastCurrent;
|
if (lastCurrent > ackMaxCurrent) ackMaxCurrent=lastCurrent;
|
||||||
// An ACK is a pulse lasting between MIN_ACK_PULSE_DURATION and MAX_ACK_PULSE_DURATION uSecs (refer @haba)
|
// An ACK is a pulse lasting between minAckPulseDuration and maxAckPulseDuration uSecs (refer @haba)
|
||||||
|
|
||||||
if (lastCurrent>ackThreshold) {
|
if (lastCurrent>ackThreshold) {
|
||||||
if (ackPulseStart==0) ackPulseStart=micros(); // leading edge of pulse detected
|
if (ackPulseStart==0) ackPulseStart=micros(); // leading edge of pulse detected
|
||||||
@ -344,7 +349,7 @@ void DCCWaveform::checkAck() {
|
|||||||
// detected trailing edge of pulse
|
// detected trailing edge of pulse
|
||||||
ackPulseDuration=micros()-ackPulseStart;
|
ackPulseDuration=micros()-ackPulseStart;
|
||||||
|
|
||||||
if (ackPulseDuration>=MIN_ACK_PULSE_DURATION && ackPulseDuration<=MAX_ACK_PULSE_DURATION) {
|
if (ackPulseDuration>=minAckPulseDuration && ackPulseDuration<=maxAckPulseDuration) {
|
||||||
ackCheckDuration=millis()-ackCheckStart;
|
ackCheckDuration=millis()-ackCheckStart;
|
||||||
ackDetected=true;
|
ackDetected=true;
|
||||||
ackPending=false;
|
ackPending=false;
|
||||||
|
@ -27,10 +27,6 @@ const int POWER_SAMPLE_ON_WAIT = 100;
|
|||||||
const int POWER_SAMPLE_OFF_WAIT = 1000;
|
const int POWER_SAMPLE_OFF_WAIT = 1000;
|
||||||
const int POWER_SAMPLE_OVERLOAD_WAIT = 20;
|
const int POWER_SAMPLE_OVERLOAD_WAIT = 20;
|
||||||
|
|
||||||
// Ack time thresholds. Unit: microseconds
|
|
||||||
const int MIN_ACK_PULSE_DURATION = 2000;
|
|
||||||
const int MAX_ACK_PULSE_DURATION = 8500;
|
|
||||||
|
|
||||||
// Number of preamble bits.
|
// Number of preamble bits.
|
||||||
const int PREAMBLE_BITS_MAIN = 16;
|
const int PREAMBLE_BITS_MAIN = 16;
|
||||||
const int PREAMBLE_BITS_PROG = 22;
|
const int PREAMBLE_BITS_PROG = 22;
|
||||||
@ -61,6 +57,11 @@ class DCCWaveform {
|
|||||||
POWERMODE getPowerMode();
|
POWERMODE getPowerMode();
|
||||||
void checkPowerOverload();
|
void checkPowerOverload();
|
||||||
int getLastCurrent();
|
int getLastCurrent();
|
||||||
|
inline int get1024Current() {
|
||||||
|
if (powerMode == POWERMODE::ON)
|
||||||
|
return (int)(lastCurrent*(long int)1024/motorDriver->getRawCurrentTripValue());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
void schedulePacket(const byte buffer[], byte byteCount, byte repeats);
|
void schedulePacket(const byte buffer[], byte byteCount, byte repeats);
|
||||||
volatile bool packetPending;
|
volatile bool packetPending;
|
||||||
volatile byte sentResetsSincePacket;
|
volatile byte sentResetsSincePacket;
|
||||||
@ -79,6 +80,12 @@ class DCCWaveform {
|
|||||||
inline void setAckLimit(int mA) {
|
inline void setAckLimit(int mA) {
|
||||||
ackLimitmA = mA;
|
ackLimitmA = mA;
|
||||||
}
|
}
|
||||||
|
inline void setMinAckPulseDuration(unsigned int i) {
|
||||||
|
minAckPulseDuration = i;
|
||||||
|
}
|
||||||
|
inline void setMaxAckPulseDuration(unsigned int i) {
|
||||||
|
maxAckPulseDuration = i;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static VirtualTimer * interruptTimer;
|
static VirtualTimer * interruptTimer;
|
||||||
@ -129,5 +136,8 @@ class DCCWaveform {
|
|||||||
unsigned int ackPulseDuration; // micros
|
unsigned int ackPulseDuration; // micros
|
||||||
unsigned long ackPulseStart; // micros
|
unsigned long ackPulseStart; // micros
|
||||||
|
|
||||||
|
unsigned int minAckPulseDuration = 2000; // micros
|
||||||
|
unsigned int maxAckPulseDuration = 8500; // micros
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "defines.h" // This should be changed to DCCEX.h when possible
|
||||||
|
#if ETHERNET_ON == true
|
||||||
#include "EthernetInterface.h"
|
#include "EthernetInterface.h"
|
||||||
#include "DIAG.h"
|
#include "DIAG.h"
|
||||||
#include "CommandDistributor.h"
|
#include "CommandDistributor.h"
|
||||||
@ -167,7 +170,5 @@ void EthernetInterface::loop()
|
|||||||
for(;count>0;count--) clients[socketOut].write(outboundRing->read());
|
for(;count>0;count--) clients[socketOut].write(outboundRing->read());
|
||||||
clients[socketOut].flush(); //maybe
|
clients[socketOut].flush(); //maybe
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
// which libraray is involved.
|
// which libraray is involved.
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef LCD_Implementation_h
|
||||||
|
#define LCD_Implementation_h
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include "LCDDisplay.h"
|
#include "LCDDisplay.h"
|
||||||
@ -51,5 +53,4 @@ LCDDisplay * LCDDisplay::lcdDisplay=0;
|
|||||||
#define CONDITIONAL_LCD_START if (false) /* NO LCD CONFIG */
|
#define CONDITIONAL_LCD_START if (false) /* NO LCD CONFIG */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif // LCD_Implementation_h
|
||||||
|
|
||||||
|
@ -83,7 +83,13 @@ the state of any outputs being monitored or controlled by a separate interface o
|
|||||||
|
|
||||||
#include "Outputs.h"
|
#include "Outputs.h"
|
||||||
#include "EEStore.h"
|
#include "EEStore.h"
|
||||||
|
#include "StringFormatter.h"
|
||||||
|
|
||||||
|
// print all output states to stream
|
||||||
|
void Output::printAll(Print *stream){
|
||||||
|
for (Output *tt = Output::firstOutput; tt != NULL; tt = tt->nextOutput)
|
||||||
|
StringFormatter::send(stream, F("<Y %d %d>"), tt->data.id, tt->data.oStatus);
|
||||||
|
} // Output::printAll
|
||||||
|
|
||||||
void Output::activate(int s){
|
void Output::activate(int s){
|
||||||
data.oStatus=(s>0); // if s>0, set status to active, else inactive
|
data.oStatus=(s>0); // if s>0, set status to active, else inactive
|
||||||
|
@ -39,6 +39,7 @@ class Output{
|
|||||||
static Output *firstOutput;
|
static Output *firstOutput;
|
||||||
struct OutputData data;
|
struct OutputData data;
|
||||||
Output *nextOutput;
|
Output *nextOutput;
|
||||||
|
static void printAll(Print *);
|
||||||
private:
|
private:
|
||||||
int num; // Chris has no idea what this is all about!
|
int num; // Chris has no idea what this is all about!
|
||||||
|
|
||||||
|
BIN
Release - Architecture Doc/CommandStation-EX-Arch-v1-0.pdf
Normal file
BIN
Release - Architecture Doc/CommandStation-EX-Arch-v1-0.pdf
Normal file
Binary file not shown.
1046
Release - Architecture Doc/CommandStation-EX-Arch-v1-0.svg
Normal file
1046
Release - Architecture Doc/CommandStation-EX-Arch-v1-0.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 65 KiB |
BIN
Release - Architecture Doc/CommandStation-EX-Arch-v1-0.vsd
Normal file
BIN
Release - Architecture Doc/CommandStation-EX-Arch-v1-0.vsd
Normal file
Binary file not shown.
84
Release - Architecture Doc/Prod-Release-Notes.md
Normal file
84
Release - Architecture Doc/Prod-Release-Notes.md
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
The DCC-EX Team is pleased to release CommandStation-EX-v3.0.0 as a Production Release. This release is a major re-write of earlier versions. We've re-architected the code-base so that it can better handle new features going forward.
|
||||||
|
|
||||||
|
**Known Bugs:**
|
||||||
|
- **Consisting through JMRI** - currently does not work in this release. A number of testers were able to develop a work around. If interested enter a Support Ticket.
|
||||||
|
- **Wi-Fi** - works, but can be challenging to use if you want to switch between AP mode and STA station mode.
|
||||||
|
- **Pololu Motor Shield** - is supported with this release, but the user may have to play around with some timings to enable programming mode due to limitation in its current sensing circuitry
|
||||||
|
|
||||||
|
**Summary of the key new features added to CommandStation-EX V3.0.1:**
|
||||||
|
- **Add back fix for jitter**
|
||||||
|
- **Add Turnouts, Outputs and Sensors to ```<s>``` command output**
|
||||||
|
|
||||||
|
**Summary of the key new features added to CommandStation-EX V3.0.0:**
|
||||||
|
|
||||||
|
- **New USB Browser Based Throttle** - WebThrottle-EX is a full front-end to controller to control the CS to run trains.
|
||||||
|
- **WiFi Support** - AP and station modes supported. Auto-detection of an ESP8266 WiFi module with AT firmware on a Mega's serial port. Connection to JMRI and WiThrottle clients.
|
||||||
|
- **Withrottle Integrations** - Act as a host for up to four WiThrottle clients concurrently.
|
||||||
|
- **Add LCD/OLED support** - OLED supported on Mega only
|
||||||
|
- **Improved CV programming routines** - checks for length of CV pulse, and breaks out of the wait state once it has received an ACK, now reading one CV per second.
|
||||||
|
- **Improved current sensing** - rewrote current sensing routines for safer operation. Current thresholds based on milliamps, not magic numbers
|
||||||
|
- **Individual track power control** - Ability to toggle power on either or both tracks, and to "JOIN" the tracks and make them output the same waveform for multiple power districts.
|
||||||
|
- **Single or Dual-Pin PWM output** - Allows control of H-bridges with PH/EN or dual PWM inputs
|
||||||
|
- **New, simpler function command** - ```<F>``` command allows setting functions based on their number, not based on a code as in ```<f>```
|
||||||
|
- **Function reminders** - Function reminders are sent in addition to speed reminders
|
||||||
|
- **Functions to F28** - All NMRA functions are now supported
|
||||||
|
- **Filters and user functions** - Ability to filter commands in the parser and execute custom code based on them. (ex: Redirect Turnout commands via NRF24)
|
||||||
|
- **Diagnostic ```<D>``` commands** - See documentation for a full list of new diagnostic commands
|
||||||
|
- **Rewrote DCC++ Parser** - more efficient operation, accepts multi-char input and uses less RAM
|
||||||
|
- **Rewritten waveform generator** - capable of using any pin for DCC waveform out, eliminating the need for jumpers
|
||||||
|
- **Rewritten packet generator** - Simplify and make smaller, remove idea of "registers" from original code
|
||||||
|
- **Add free RAM messages** - Free RAM messages are now printed whenever there is a decerase in available RAM
|
||||||
|
- **Fix EEPROM bugs**
|
||||||
|
- **Number of locos discovery command** - ```<#>``` command
|
||||||
|
- **Support for more locomotives** - 20 locomotives on an UNO and 50 an a Mega.
|
||||||
|
- **Automatic slot managment** - slot variable in throttle/function commands are ignored and slot management is taken care of automatically. ```<!>``` command added to release locos from memory.
|
||||||
|
|
||||||
|
|
||||||
|
**Key Contributors**
|
||||||
|
|
||||||
|
**Project Lead**
|
||||||
|
- Fred Decker - Holly Springs, North Carolina, USA (FlightRisk)
|
||||||
|
|
||||||
|
**CommandStation-EX Developers**
|
||||||
|
- Chris Harlow - Bournemouth, UK (UKBloke)
|
||||||
|
- Harald Barth - Stockholm, Sweden (Haba)
|
||||||
|
- Fred Decker - Holly Springs, North Carolina, USA (FlightRisk)
|
||||||
|
- Dave Cutting - Logan, Utah, USA (Dave Cutting/ David Cutting)
|
||||||
|
- M Steve Todd - - Engine Driver and JMRI Interface
|
||||||
|
- Scott Catalanno - Pennsylvania
|
||||||
|
- Gregor Baues - Île-de-France, France (grbba)
|
||||||
|
|
||||||
|
**exInstaller Software**
|
||||||
|
- Anthony W - Dayton, Ohio, USA (Dex, Dex++)
|
||||||
|
|
||||||
|
**Website and Documentation**
|
||||||
|
- Mani Kumar - Bangalor, India (Mani / Mani Kumar)
|
||||||
|
- Fred Decker - Holly Springs, North Carolina, USA (FlightRisk)
|
||||||
|
- Dave Cutting - Logan, Utah, USA (Dave Cutting/ David Cutting)
|
||||||
|
- Roger Beschizza - Dorset, UK (Roger Beschizza)
|
||||||
|
- Keith Ledbetter - Chicago, Illinois, USA (Keith Ledbetter)
|
||||||
|
- Kevin Smith - (KCSmith)
|
||||||
|
|
||||||
|
**WebThrotle-EX**
|
||||||
|
- Fred Decker - Holly Springs, NC (FlightRisk/FrightRisk)
|
||||||
|
- Mani Kumar - Bangalor, India (Mani /Mani Kumar)
|
||||||
|
- Matt H -
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Beta Testing / Release Management / Support**
|
||||||
|
- Larry Dribin - Release Management
|
||||||
|
- Keith Ledbetter
|
||||||
|
- BradVan der Elst
|
||||||
|
- Andrew Pye
|
||||||
|
- Mike Bowers
|
||||||
|
- Randy McKenzie
|
||||||
|
- Roberto Bravin
|
||||||
|
- Sim Brigden
|
||||||
|
- Alan Lautenslager
|
||||||
|
- Martin Bafver
|
||||||
|
- Mário André Silva
|
||||||
|
- Anthony Kochevar
|
||||||
|
- Gajanatha Kobbekaduwe
|
||||||
|
- Sumner Patterson
|
||||||
|
- Paul - Virginia, USA
|
23
Release - Architecture Doc/Rough Release-Notes.md
Normal file
23
Release - Architecture Doc/Rough Release-Notes.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# CommandStation-EX Release Notes
|
||||||
|
|
||||||
|
## v3.0.0
|
||||||
|
|
||||||
|
- **WiFi Support** - AP and station modes supported. Auto-detection of an ESP8266 WiFi module with AT firmware on a Mega's serial port. Connection to JMRI and WiThrottle clients.
|
||||||
|
- **Withrottle Integrations** - Act as a host for four WiThrottle clients concurrently.
|
||||||
|
- **Add LCD/OLED support** - OLED supported on Mega only
|
||||||
|
- **Improved CV programming routines** - checks for length of CV pulse, and breaks out of the wait state once it has received an ACK, now reading one CV per second.
|
||||||
|
- **Improved current sensing** - rewrote current sensing routines for safer operation. Current thresholds based on milliamps, not magic numbers
|
||||||
|
- **Individual track power control** - Ability to toggle power on either or both tracks, and to "JOIN" the tracks and make them output the same waveform for multiple power districts.
|
||||||
|
- **Single or Dual-Pin PWM output** - Allows control of H-bridges with PH/EN or dual PWM inputs
|
||||||
|
- **New, simpler function command** - ```<F>``` command allows setting functions based on their number, not based on a code as in ```<f>```
|
||||||
|
- **Function reminders** - Function reminders are sent in addition to speed reminders
|
||||||
|
- **Functions to F28** - All NMRA functions are now supported
|
||||||
|
- **Filters and user functions** - Ability to filter commands in the parser and execute custom code based on them
|
||||||
|
- **Diagnostic ```<D>``` commands** - See documentation for a full list of new diagnostic commands
|
||||||
|
- **Rewrote DCC++ Parser** - more efficient operation, accepts multi-char input and uses less RAM
|
||||||
|
- **Rewritten waveform generator** - capable of using any pin for DCC waveform out, eliminating the need for jumpers
|
||||||
|
- **Rewritten packet generator** - Simplify and make smaller, remove idea of "registers" from original code
|
||||||
|
- **Add free RAM messages** - Free RAM messages are now printed whenever there is a decerase in available RAM
|
||||||
|
- **Fix EEPROM bugs**
|
||||||
|
- **Support for more decoders** - Support for 20 (Uno) or 50 (Mega) mobile decoders, number automaticlaly recognized by JMRI.
|
||||||
|
- **Automatic slot managment** - slot variable in throttle/function commands are ignored and slot management is taken care of automatically. ```<!>``` command added to release locos from memory.
|
@ -262,10 +262,10 @@ void WiThrottle::locoAction(RingStream * stream, byte* aval, char throttleChar,
|
|||||||
switch (aval[0]) {
|
switch (aval[0]) {
|
||||||
case 'V': // Vspeed
|
case 'V': // Vspeed
|
||||||
{
|
{
|
||||||
byte locospeed=WiTToDCCSpeed(getInt(aval+1));
|
int witSpeed=getInt(aval+1);
|
||||||
LOOPLOCOS(throttleChar, cab) {
|
LOOPLOCOS(throttleChar, cab) {
|
||||||
DCC::setThrottle(myLocos[loco].cab, locospeed, DCC::getThrottleDirection(myLocos[loco].cab));
|
DCC::setThrottle(myLocos[loco].cab, WiTToDCCSpeed(witSpeed), DCC::getThrottleDirection(myLocos[loco].cab));
|
||||||
StringFormatter::send(stream,F("M%cA%c%d<;>V%d\n"), throttleChar, LorS(myLocos[loco].cab), myLocos[loco].cab, locospeed);
|
StringFormatter::send(stream,F("M%cA%c%d<;>V%d\n"), throttleChar, LorS(myLocos[loco].cab), myLocos[loco].cab, witSpeed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -34,6 +34,10 @@ const unsigned long LOOP_TIMEOUT = 2000;
|
|||||||
bool WifiInterface::connected = false;
|
bool WifiInterface::connected = false;
|
||||||
Stream * WifiInterface::wifiStream;
|
Stream * WifiInterface::wifiStream;
|
||||||
|
|
||||||
|
#ifndef WIFI_CONNECT_TIMEOUT
|
||||||
|
// Tested how long it takes to FAIL an unknown SSID on firmware 1.7.4.
|
||||||
|
#define WIFI_CONNECT_TIMEOUT 14000
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
@ -170,15 +174,16 @@ wifiSerialState WifiInterface::setup2(const FSH* SSid, const FSH* password,
|
|||||||
|
|
||||||
// If the source code looks unconfigured, check if the
|
// If the source code looks unconfigured, check if the
|
||||||
// ESP8266 is preconfigured. We check the first 13 chars
|
// ESP8266 is preconfigured. We check the first 13 chars
|
||||||
// of the password.
|
// of the SSid.
|
||||||
if (strncmp_P("Your network ",(const char*)password,13) == 0) {
|
const char *yourNetwork = "Your network ";
|
||||||
|
if (strncmp_P(yourNetwork, (const char*)SSid, 13) == 0 || ((const char *)SSid)[0] == '\0') {
|
||||||
delay(8000); // give a preconfigured ES8266 a chance to connect to a router
|
delay(8000); // give a preconfigured ES8266 a chance to connect to a router
|
||||||
|
// typical connect time approx 7 seconds
|
||||||
StringFormatter::send(wifiStream, F("AT+CIFSR\r\n"));
|
StringFormatter::send(wifiStream, F("AT+CIFSR\r\n"));
|
||||||
if (checkForOK(5000, (const char*) F("+CIFSR:STAIP"), true,false))
|
if (checkForOK(5000, (const char*) F("+CIFSR:STAIP"), true,false))
|
||||||
if (!checkForOK(1000, (const char*) F("0.0.0.0"), true,false))
|
if (!checkForOK(1000, (const char*) F("0.0.0.0"), true,false))
|
||||||
ipOK = true;
|
ipOK = true;
|
||||||
} else {
|
} else { // Should this really be "else" here /haba
|
||||||
|
|
||||||
if (!ipOK) {
|
if (!ipOK) {
|
||||||
|
|
||||||
@ -191,7 +196,7 @@ wifiSerialState WifiInterface::setup2(const FSH* SSid, const FSH* password,
|
|||||||
// AT command early version supports CWJAP/CWSAP
|
// AT command early version supports CWJAP/CWSAP
|
||||||
if (SSid) {
|
if (SSid) {
|
||||||
StringFormatter::send(wifiStream, F("AT+CWJAP=\"%S\",\"%S\"\r\n"), SSid, password);
|
StringFormatter::send(wifiStream, F("AT+CWJAP=\"%S\",\"%S\"\r\n"), SSid, password);
|
||||||
ipOK = checkForOK(16000, OK_SEARCH, true);
|
ipOK = checkForOK(WIFI_CONNECT_TIMEOUT, OK_SEARCH, true);
|
||||||
}
|
}
|
||||||
DIAG(F("\n**\n"));
|
DIAG(F("\n**\n"));
|
||||||
|
|
||||||
@ -203,10 +208,9 @@ wifiSerialState WifiInterface::setup2(const FSH* SSid, const FSH* password,
|
|||||||
|
|
||||||
if (SSid) {
|
if (SSid) {
|
||||||
StringFormatter::send(wifiStream, F("AT+CWJAP_CUR=\"%S\",\"%S\"\r\n"), SSid, password);
|
StringFormatter::send(wifiStream, F("AT+CWJAP_CUR=\"%S\",\"%S\"\r\n"), SSid, password);
|
||||||
ipOK = checkForOK(20000, OK_SEARCH, true);
|
ipOK = checkForOK(WIFI_CONNECT_TIMEOUT, OK_SEARCH, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delay(8000); // give a preconfigured ES8266 a chance to connect to a router
|
|
||||||
|
|
||||||
if (ipOK) {
|
if (ipOK) {
|
||||||
// But we really only have the ESSID and password correct
|
// But we really only have the ESSID and password correct
|
||||||
@ -243,9 +247,15 @@ wifiSerialState WifiInterface::setup2(const FSH* SSid, const FSH* password,
|
|||||||
while (wifiStream->available()) StringFormatter::printEscape( wifiStream->read()); /// THIS IS A DIAG IN DISGUISE
|
while (wifiStream->available()) StringFormatter::printEscape( wifiStream->read()); /// THIS IS A DIAG IN DISGUISE
|
||||||
|
|
||||||
int i=0;
|
int i=0;
|
||||||
do StringFormatter::send(wifiStream, F("AT+CWSAP=\"DCCEX_%s\",\"PASS_%s\",1,4\r\n"), macTail, macTail);
|
do {
|
||||||
while (i++<2 && !checkForOK(16000, OK_SEARCH, true)); // do twice if necessary but ignore failure as AP mode may still be ok
|
if (strncmp_P(yourNetwork, (const char*)password, 13) == 0) {
|
||||||
|
// unconfigured
|
||||||
|
StringFormatter::send(wifiStream, F("AT+CWSAP=\"DCCEX_%s\",\"PASS_%s\",1,4\r\n"), macTail, macTail);
|
||||||
|
} else {
|
||||||
|
// password configured by user
|
||||||
|
StringFormatter::send(wifiStream, F("AT+CWSAP=\"DCCEX_%s\",\"%s\",1,4\r\n"), macTail, password);
|
||||||
|
}
|
||||||
|
} while (i++<2 && !checkForOK(WIFI_CONNECT_TIMEOUT, OK_SEARCH, true)); // do twice if necessary but ignore failure as AP mode may still be ok
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
StringFormatter::send(wifiStream, F("AT+CWSAP_CUR=\"DCCEX_%s\",\"PASS_%s\",1,4\r\n"), macTail, macTail);
|
StringFormatter::send(wifiStream, F("AT+CWSAP_CUR=\"DCCEX_%s\",\"PASS_%s\",1,4\r\n"), macTail, macTail);
|
||||||
@ -257,17 +267,17 @@ wifiSerialState WifiInterface::setup2(const FSH* SSid, const FSH* password,
|
|||||||
}
|
}
|
||||||
|
|
||||||
StringFormatter::send(wifiStream, F("AT+CIPSERVER=0\r\n")); // turn off tcp server (to clean connections before CIPMUX=1)
|
StringFormatter::send(wifiStream, F("AT+CIPSERVER=0\r\n")); // turn off tcp server (to clean connections before CIPMUX=1)
|
||||||
checkForOK(10000, OK_SEARCH, true); // ignore result in case it already was off
|
checkForOK(1000, OK_SEARCH, true); // ignore result in case it already was off
|
||||||
|
|
||||||
StringFormatter::send(wifiStream, F("AT+CIPMUX=1\r\n")); // configure for multiple connections
|
StringFormatter::send(wifiStream, F("AT+CIPMUX=1\r\n")); // configure for multiple connections
|
||||||
if (!checkForOK(10000, OK_SEARCH, true)) return WIFI_DISCONNECTED;
|
if (!checkForOK(1000, OK_SEARCH, true)) return WIFI_DISCONNECTED;
|
||||||
|
|
||||||
StringFormatter::send(wifiStream, F("AT+CIPSERVER=1,%d\r\n"), port); // turn on server on port
|
StringFormatter::send(wifiStream, F("AT+CIPSERVER=1,%d\r\n"), port); // turn on server on port
|
||||||
if (!checkForOK(10000, OK_SEARCH, true)) return WIFI_DISCONNECTED;
|
if (!checkForOK(1000, OK_SEARCH, true)) return WIFI_DISCONNECTED;
|
||||||
#endif //DONT_TOUCH_WIFI_CONF
|
#endif //DONT_TOUCH_WIFI_CONF
|
||||||
|
|
||||||
StringFormatter::send(wifiStream, F("AT+CIFSR\r\n")); // Display ip addresses to the DIAG
|
StringFormatter::send(wifiStream, F("AT+CIFSR\r\n")); // Display ip addresses to the DIAG
|
||||||
if (!checkForOK(10000, OK_SEARCH, true, false)) return WIFI_DISCONNECTED;
|
if (!checkForOK(1000, OK_SEARCH, true, false)) return WIFI_DISCONNECTED;
|
||||||
DIAG(F("\nPORT=%d\n"),port);
|
DIAG(F("\nPORT=%d\n"),port);
|
||||||
|
|
||||||
return WIFI_CONNECTED;
|
return WIFI_CONNECTED;
|
||||||
|
@ -44,15 +44,45 @@ The configuration file for DCC++ EX Command Station
|
|||||||
//
|
//
|
||||||
// DEFINE WiFi Parameters (only in effect if WIFI is on)
|
// DEFINE WiFi Parameters (only in effect if WIFI is on)
|
||||||
//
|
//
|
||||||
|
// If DONT_TOUCH_WIFI_CONF is set, all WIFI config will be done with
|
||||||
|
// the <+> commands and this sketch will not change anything over
|
||||||
|
// AT commands and the other WIFI_* defines below do not have any effect.
|
||||||
//#define DONT_TOUCH_WIFI_CONF
|
//#define DONT_TOUCH_WIFI_CONF
|
||||||
//
|
//
|
||||||
// if DONT_TOUCH_WIFI_CONF is set, all WIFI config will be done with
|
// WIFI_SSID is the network name IF you want to use your existing home network.
|
||||||
// the <+> commands and this sketch will not change anything over
|
// Do NOT change this if you want to use the WiFi in Access Point (AP) mode.
|
||||||
// AT commands and the WIFI_* defines below do not have any effect.
|
|
||||||
//
|
//
|
||||||
|
// If you do NOT set the WIFI_SSID, the WiFi chip will first try
|
||||||
|
// to connect to the previously configured network and if that fails
|
||||||
|
// fall back to Access Point mode. The SSID of the AP will be
|
||||||
|
// automatically set to DCCEX_*.
|
||||||
|
//
|
||||||
|
// Your SSID may not conain ``"'' (double quote, ASCII 0x22).
|
||||||
#define WIFI_SSID "Your network name"
|
#define WIFI_SSID "Your network name"
|
||||||
|
//
|
||||||
|
// WIFI_PASSWORD is the network password for your home network or if
|
||||||
|
// you want to change the password from default AP mode password
|
||||||
|
// to the AP password you want.
|
||||||
|
// Your password may not conain ``"'' (double quote, ASCII 0x22).
|
||||||
#define WIFI_PASSWORD "Your network passwd"
|
#define WIFI_PASSWORD "Your network passwd"
|
||||||
|
//
|
||||||
|
// WIFI_HOSTNAME: You probably don't need to change this
|
||||||
#define WIFI_HOSTNAME "dccex"
|
#define WIFI_HOSTNAME "dccex"
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Wifi connect timeout in milliseconds. Default is 14000 (14 seconds). You only need
|
||||||
|
// to set this if you have an extremely slow Wifi router.
|
||||||
|
//
|
||||||
|
//#define WIFI_CONNECT_TIMEOUT 14000
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ENABLE_ETHERNET: Set to true if you have an Arduino Ethernet card (wired). This
|
||||||
|
// is not for Wifi. You will then need the Arduino Ethernet library as well
|
||||||
|
//
|
||||||
|
//#define ENABLE_ETHERNET true
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
@ -66,7 +96,18 @@ The configuration file for DCC++ EX Command Station
|
|||||||
//
|
//
|
||||||
// Uncomment to use with Ethernet Shields
|
// Uncomment to use with Ethernet Shields
|
||||||
//
|
//
|
||||||
|
// Ethernet Shields do not have have a MAC address in hardware. There may be one on
|
||||||
|
// a sticker on the Shield that you should use. Otherwise choose one of the ones below
|
||||||
|
// Be certain that no other device on your network has this same MAC address!
|
||||||
|
//
|
||||||
|
// 52:b8:8a:8e:ce:21
|
||||||
|
// e3:e9:73:e1:db:0d
|
||||||
|
// 54:2b:13:52:ac:0c
|
||||||
|
|
||||||
// NOTE: This is not used with ESP8266 WiFi modules.
|
// NOTE: This is not used with ESP8266 WiFi modules.
|
||||||
|
|
||||||
|
//#define MAC_ADDRESS { 0x52, 0xB8, 0x8A, 0x8E, 0xCE, 0x21 } // MAC address of your networking card found on the sticker on your card or take one from above
|
||||||
|
|
||||||
//
|
//
|
||||||
// #define MAC_ADDRESS { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF }
|
// #define MAC_ADDRESS { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF }
|
||||||
|
|
||||||
|
@ -36,7 +36,10 @@ lib_deps =
|
|||||||
DIO2
|
DIO2
|
||||||
arduino-libraries/Ethernet
|
arduino-libraries/Ethernet
|
||||||
SPI
|
SPI
|
||||||
mathertel/LiquidCrystal_PCF8574
|
marcoschwartz/LiquidCrystal_I2C
|
||||||
|
Adafruit/Adafruit_BusIO
|
||||||
|
Adafruit/Adafruit_SSD1306
|
||||||
|
Adafruit/Adafruit-GFX-Library
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
monitor_flags = --echo
|
monitor_flags = --echo
|
||||||
|
|
||||||
@ -49,7 +52,7 @@ lib_deps =
|
|||||||
DIO2
|
DIO2
|
||||||
arduino-libraries/Ethernet
|
arduino-libraries/Ethernet
|
||||||
SPI
|
SPI
|
||||||
mathertel/LiquidCrystal_PCF8574
|
marcoschwartz/LiquidCrystal_I2C
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
monitor_flags = --echo
|
monitor_flags = --echo
|
||||||
|
|
||||||
@ -62,7 +65,7 @@ lib_deps =
|
|||||||
DIO2
|
DIO2
|
||||||
arduino-libraries/Ethernet
|
arduino-libraries/Ethernet
|
||||||
SPI
|
SPI
|
||||||
mathertel/LiquidCrystal_PCF8574
|
marcoschwartz/LiquidCrystal_I2C
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
monitor_flags = --echo
|
monitor_flags = --echo
|
||||||
build_flags = "-DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_UNO_WIFI_DEV_ED -DARDUINO_ARCH_AVR -DESP_CH_UART -DESP_CH_UART_BR=19200"g
|
build_flags = "-DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_UNO_WIFI_DEV_ED -DARDUINO_ARCH_AVR -DESP_CH_UART -DESP_CH_UART_BR=19200"g
|
||||||
@ -76,6 +79,6 @@ lib_deps =
|
|||||||
DIO2
|
DIO2
|
||||||
arduino-libraries/Ethernet
|
arduino-libraries/Ethernet
|
||||||
SPI
|
SPI
|
||||||
mathertel/LiquidCrystal_PCF8574
|
marcoschwartz/LiquidCrystal_I2C
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
monitor_flags = --echo
|
monitor_flags = --echo
|
||||||
|
Loading…
Reference in New Issue
Block a user