2020-07-03 18:35:02 +02:00
|
|
|
/*
|
|
|
|
* © 2020, Chris Harlow. All rights reserved.
|
|
|
|
*
|
|
|
|
* This file is part of Asbelos DCC API
|
|
|
|
*
|
|
|
|
* This is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* It is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-05-24 17:07:16 +02:00
|
|
|
#include "DCC.h"
|
2020-05-24 00:02:54 +02:00
|
|
|
#include "DIAG.h"
|
2020-06-04 21:55:18 +02:00
|
|
|
#include "DCCEXParser.h"
|
2020-06-11 14:35:16 +02:00
|
|
|
#include "WifiInterface.h"
|
2020-05-24 00:22:12 +02:00
|
|
|
|
2020-06-22 11:54:57 +02:00
|
|
|
// this code is here to demonstrate use of the DCC API and other techniques
|
2020-05-24 00:22:12 +02:00
|
|
|
|
2020-06-19 11:45:08 +02:00
|
|
|
// myFilter is an example of an OPTIONAL command filter used to intercept < > commands from
|
|
|
|
// the usb or wifi streamm. It demonstrates how a command may be intercepted
|
2020-06-22 11:54:57 +02:00
|
|
|
// or even a new command created without having to break open the API library code.
|
|
|
|
// The filter is permitted to use or modify the parameter list before passing it on to
|
2020-06-28 11:21:27 +02:00
|
|
|
// the standard parser. By setting the opcode to 0, the standard parser will
|
2020-06-19 11:45:08 +02:00
|
|
|
// just ignore the command on the assumption that you have already handled it.
|
|
|
|
//
|
|
|
|
// The filter must be enabled by calling the DCC EXParser::setFilter method, see use in setup().
|
|
|
|
|
2020-08-01 17:32:16 +02:00
|
|
|
void myFilter(Print * stream, byte & opcode, byte & paramCount, int p[]) {
|
2020-06-29 12:37:05 +02:00
|
|
|
(void)stream; // avoid compiler warning if we don't access this parameter
|
2020-06-23 21:01:43 +02:00
|
|
|
switch (opcode) {
|
2020-07-30 16:34:56 +02:00
|
|
|
case '!': // Create a bespoke new command to clear all loco reminders <!> or specific locos e.g <! 3 4 99>
|
|
|
|
if (paramCount==0) DCC::forgetAllLocos();
|
|
|
|
else for (int i=0;i<paramCount;i++) DCC::forgetLoco(p[i]);
|
|
|
|
opcode=0; // tell parser to ignore this command as we have done it already
|
2020-06-22 11:54:57 +02:00
|
|
|
break;
|
2020-06-19 11:45:08 +02:00
|
|
|
default: // drop through and parser will use the command unaltered.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-05-24 17:07:16 +02:00
|
|
|
|
2020-06-19 11:45:08 +02:00
|
|
|
// Callback functions are necessary if you call any API that must wait for a response from the
|
|
|
|
// programming track. The API must return immediately otherwise other loop() functions would be blocked.
|
|
|
|
// Your callback function will be invoked when the data arrives from the prog track.
|
2020-06-28 11:21:27 +02:00
|
|
|
// See the DCC:getLocoId example in the setup function.
|
|
|
|
|
2020-05-26 13:44:02 +02:00
|
|
|
|
2020-06-07 17:29:53 +02:00
|
|
|
void myCallback(int result) {
|
2020-06-08 14:04:47 +02:00
|
|
|
DIAG(F("\n getting Loco Id callback result=%d"),result);
|
2020-06-07 17:29:53 +02:00
|
|
|
}
|
2020-05-24 00:02:54 +02:00
|
|
|
|
2020-06-18 20:36:37 +02:00
|
|
|
|
2020-06-23 18:43:50 +02:00
|
|
|
// Create a serial command parser... This is OPTIONAL if you don't need to handle JMRI type commands
|
2020-06-19 11:45:08 +02:00
|
|
|
// from the Serial port.
|
2020-06-11 14:35:16 +02:00
|
|
|
DCCEXParser serialParser;
|
2020-06-10 18:31:26 +02:00
|
|
|
|
2020-06-23 18:43:50 +02:00
|
|
|
|
|
|
|
// Try monitoring the memory
|
|
|
|
#include "freeMemory.h"
|
2020-07-24 14:46:23 +02:00
|
|
|
int ramLowWatermark=32767; // This figure gets overwritten dynamically in loop()
|
2020-06-23 18:43:50 +02:00
|
|
|
|
2020-05-24 00:02:54 +02:00
|
|
|
void setup() {
|
2020-06-28 11:21:27 +02:00
|
|
|
|
|
|
|
// The main sketch has responsibilities during setup()
|
|
|
|
|
|
|
|
// Responsibility 1: Start the usb connection for diagnostics and possible JMRI input
|
2020-07-24 13:00:07 +02:00
|
|
|
// DIAGSERAL is normally Serial but uses SerialUSB on a SAMD processor
|
|
|
|
DIAGSERIAL.begin(115200);
|
2020-07-25 02:40:20 +02:00
|
|
|
while(!DIAGSERIAL);
|
2020-06-28 11:21:27 +02:00
|
|
|
|
2020-08-15 12:32:32 +02:00
|
|
|
// Responsibility 2: Start the DCC engine.
|
|
|
|
// Note: this provides DCC with two motor drivers, main and prog, which handle the motor shield(s)
|
|
|
|
// Standard supported devices have pre-configured macros but custome hardware installations require
|
|
|
|
// detailed pin mappings and may also require modified subclasses of the MotorDriver to implement specialist logic.
|
|
|
|
|
|
|
|
DCC::begin(new MotorDriver(MAIN_POWER_PIN,MAIN_SIGNAL_PIN,MAIN_SIGNAL_PIN_ALT,MAIN_BRAKE_PIN,MAIN_SENSE_PIN,MAIN_SENSE_FACTOR, MAIN_MAX_MILLIAMPS,MAIN_FAULT_PIN),
|
|
|
|
new MotorDriver(PROG_POWER_PIN,PROG_SIGNAL_PIN,PROG_SIGNAL_PIN_ALT,PROG_BRAKE_PIN,PROG_SENSE_PIN,PROG_SENSE_FACTOR, PROG_MAX_MILLIAMPS,PROG_FAULT_PIN));
|
|
|
|
|
2020-06-28 11:21:27 +02:00
|
|
|
|
|
|
|
// Responsibility 3: Optionally Start the WiFi interface if required.
|
|
|
|
// NOTE: On a Uno you will have to provide a SoftwareSerial
|
|
|
|
// configured for the pins connected to the Wifi card
|
|
|
|
// and a 9600 baud rate.
|
|
|
|
// setup(serial, F(router name), F(password) , port)
|
|
|
|
//
|
2020-07-03 00:19:59 +02:00
|
|
|
#ifdef WIFI
|
2020-07-25 15:40:59 +02:00
|
|
|
Serial1.begin(115200);
|
2020-08-01 18:33:10 +02:00
|
|
|
WifiInterface::setup(Serial1, F(WIFI_CONNECT_TO_SSID), F(WIFI_CONNECT_PASSWORD),F("DCCEX"),F("CVReader"),3532); // (3532 is 0xDCC decimal... )
|
2020-07-03 00:19:59 +02:00
|
|
|
#endif
|
2020-06-28 11:21:27 +02:00
|
|
|
|
|
|
|
// This is just for demonstration purposes
|
2020-06-08 14:04:47 +02:00
|
|
|
DIAG(F("\n===== CVReader demonstrating DCC::getLocoId() call ==========\n"));
|
|
|
|
DCC::getLocoId(myCallback); // myCallback will be called with the result
|
2020-06-28 11:21:27 +02:00
|
|
|
DIAG(F("\n===== DCC::getLocoId has returned, but the callback wont be executed until we are in loop() ======\n"));
|
2020-06-19 11:45:08 +02:00
|
|
|
|
2020-06-28 11:21:27 +02:00
|
|
|
// Optionally tell the command parser to use my example filter.
|
|
|
|
// This will intercept JMRI commands from both USB and Wifi
|
2020-06-18 20:36:37 +02:00
|
|
|
DCCEXParser::setFilter(myFilter);
|
2020-06-28 11:21:27 +02:00
|
|
|
|
2020-06-19 11:45:08 +02:00
|
|
|
DIAG(F("\nReady for JMRI commands\n"));
|
2020-06-23 18:43:50 +02:00
|
|
|
|
2020-05-24 00:02:54 +02:00
|
|
|
}
|
|
|
|
|
2020-06-11 14:35:16 +02:00
|
|
|
void loop() {
|
2020-06-28 11:21:27 +02:00
|
|
|
// The main sketch has responsibilities during loop()
|
|
|
|
|
|
|
|
// Responsibility 1: Handle DCC background processes
|
|
|
|
// (loco reminders and power checks)
|
|
|
|
DCC::loop();
|
2020-05-26 13:44:02 +02:00
|
|
|
|
2020-06-28 11:21:27 +02:00
|
|
|
// Responsibility 2: handle any incoming commands on USB connection
|
2020-07-24 13:00:07 +02:00
|
|
|
serialParser.loop(DIAGSERIAL);
|
2020-06-19 11:45:08 +02:00
|
|
|
|
2020-06-28 11:21:27 +02:00
|
|
|
// Responsibility 3: Optionally handle any incoming WiFi traffic
|
2020-07-03 00:19:59 +02:00
|
|
|
#ifdef WIFI
|
2020-08-01 17:32:16 +02:00
|
|
|
WifiInterface::loop();
|
2020-07-03 00:19:59 +02:00
|
|
|
#endif
|
2020-06-23 18:43:50 +02:00
|
|
|
|
2020-07-24 14:46:23 +02:00
|
|
|
// Your additional code
|
|
|
|
|
|
|
|
// OPtionally report any decrease in memory (will automatically trigger on first call)
|
2020-06-23 18:43:50 +02:00
|
|
|
int freeNow=freeMemory();
|
2020-07-24 14:46:23 +02:00
|
|
|
if (freeNow<ramLowWatermark) {
|
|
|
|
ramLowWatermark=freeNow;
|
|
|
|
DIAG(F("\nFree RAM=%d\n"),ramLowWatermark);
|
2020-06-23 18:43:50 +02:00
|
|
|
}
|
2020-05-26 00:03:11 +02:00
|
|
|
}
|