mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-27 01:56:14 +01:00
Merge branch 'feature/config-saveram' into feature/config
Conflicts: objdump.bat
This commit is contained in:
commit
d45d35f32f
|
@ -2,38 +2,15 @@
|
|||
// © 2020, Chris Harlow. All rights reserved.
|
||||
//
|
||||
// This file is a demonstattion of setting up a DCC-EX
|
||||
// Command station to support direct connection of WiThrottle devices
|
||||
// Command station with optional support for direct connection of WiThrottle devices
|
||||
// such as "Engine Driver". If you contriol your layout through JMRI
|
||||
// then DON'T connect throttles to this wifi, connect them to JMRI.
|
||||
//
|
||||
// This is just 3 statements longer than the basic setup.
|
||||
//
|
||||
// THIS SETUP DOES NOT APPLY TO ARDUINO UNO WITH ONLY A SINGLE SERIAL PORT.
|
||||
// REFER TO SEPARATE EXAMPLE.
|
||||
// THE WIFI FEATURE IS NOT SUPPORTED ON ARDUINO DEVICES WITH ONLY 2KB RAM.
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This defines the speed at which the Arduino will communicate with the ESP8266 module.
|
||||
// Currently only Arduino Mega and 115200 is supported.
|
||||
#define WIFI_SERIAL_LINK_SPEED 115200
|
||||
|
||||
#include "config.h"
|
||||
#include "DCC.h"
|
||||
#include "DIAG.h"
|
||||
#include "DCCEXParser.h"
|
||||
#include "version.h"
|
||||
#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560))
|
||||
#include "WifiInterface.h"
|
||||
#endif
|
||||
#if ENABLE_FREE_MEM_WARNING
|
||||
#include "freeMemory.h"
|
||||
int ramLowWatermark = 32767; // This figure gets overwritten dynamically in loop()
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_MEGAAVR)
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "DCCEX.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
@ -48,69 +25,9 @@ LiquidCrystal_I2C lcdDisplay = LiquidCrystal_I2C(LCD_ADDRESS, LCD_COLUMNS, LCD_L
|
|||
#endif
|
||||
#endif
|
||||
|
||||
// this code is here to demonstrate use of the DCC API and other techniques
|
||||
|
||||
// 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
|
||||
// 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
|
||||
// the standard parser. By setting the opcode to 0, the standard parser will
|
||||
// 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().
|
||||
#if ENABLE_CUSTOM_FILTER
|
||||
void myComandFilter(Print *stream, byte &opcode, byte ¶mCount, int p[])
|
||||
{
|
||||
(void)stream; // avoid compiler warning if we don't access this parameter
|
||||
switch (opcode)
|
||||
{
|
||||
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
|
||||
break;
|
||||
default: // drop through and parser will use the command unaltered.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This is an OPTIONAL example of a HTTP filter...
|
||||
// If you have configured wifi and an HTTP request is received on the Wifi connection
|
||||
// it will normally be rejected 404 Not Found.
|
||||
|
||||
// If you wish to handle HTTP requests, you can create a filter and ask the WifiInterface to
|
||||
// call your code for each detected http request.
|
||||
|
||||
void myHttpFilter(Print *stream, byte *cmd)
|
||||
{
|
||||
(void)cmd; // Avoid compiler warning because this example doesnt use this parameter
|
||||
|
||||
// BEWARE - As soon as you start responding, the cmd buffer is trashed!
|
||||
// You must get everything you need from it before using StringFormatter::send!
|
||||
|
||||
StringFormatter::send(stream, F("HTTP/1.1 200 OK\nContent-Type: text/html\nConnnection: close\n\n"));
|
||||
StringFormatter::send(stream, F("<html><body>This is my HTTP filter responding.<br/></body></html>"));
|
||||
}
|
||||
#endif
|
||||
|
||||
// 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.
|
||||
// See the DCC:getLocoId example in the setup function.
|
||||
#if ENABLE_CUSTOM_CALLBACK
|
||||
void myCallback(int result)
|
||||
{
|
||||
DIAG(F("\n getting Loco Id callback result=%d"), result);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create a serial command parser... Enables certain diagnostics and commands
|
||||
// to be issued from the USB serial console
|
||||
// This is NOT intended for JMRI....
|
||||
|
||||
// Create a serial command parser for the USB connection,
|
||||
// This supports JMRI or manual diagnostics and commands
|
||||
// to be issued from the USB serial console.
|
||||
DCCEXParser serialParser;
|
||||
|
||||
void setup()
|
||||
|
@ -156,20 +73,7 @@ void setup()
|
|||
// NOTE: References to Serial1 are for the serial port used to connect
|
||||
// your wifi chip/shield.
|
||||
|
||||
// Optionally tell the command parser to use my example filter.
|
||||
// This will intercept JMRI commands from both USB and Wifi
|
||||
#if ENABLE_CUSTOM_FILTER
|
||||
DCCEXParser::setFilter(myComandFilter);
|
||||
#endif
|
||||
|
||||
#if ENABLE_CUSTOM_CALLBACK
|
||||
// This is just for demonstration purposes
|
||||
DIAG(F("\n===== DCCEX demonstrating DCC::getLocoId() call ==========\n"));
|
||||
DCC::getLocoId(myCallback); // myCallback will be called with the result
|
||||
DIAG(F("\n===== DCC::getLocoId has returned, but the callback wont be executed until we are in loop() ======\n"));
|
||||
#endif
|
||||
|
||||
#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560))
|
||||
#ifdef WIFI_ON
|
||||
bool wifiUp = false;
|
||||
const __FlashStringHelper *wifiESSID = F(WIFI_SSID);
|
||||
const __FlashStringHelper *wifiPassword = F(WIFI_PASSWORD);
|
||||
|
@ -178,17 +82,21 @@ void setup()
|
|||
|
||||
Serial1.begin(WIFI_SERIAL_LINK_SPEED);
|
||||
wifiUp = WifiInterface::setup(Serial1, wifiESSID, wifiPassword, dccex, port);
|
||||
#if NUM_SERIAL > 1
|
||||
if (!wifiUp)
|
||||
{
|
||||
Serial2.begin(WIFI_SERIAL_LINK_SPEED);
|
||||
wifiUp = WifiInterface::setup(Serial2, wifiESSID, wifiPassword, dccex, port);
|
||||
}
|
||||
#if NUM_SERIAL > 2
|
||||
if (!wifiUp)
|
||||
{
|
||||
Serial3.begin(WIFI_SERIAL_LINK_SPEED);
|
||||
wifiUp = WifiInterface::setup(Serial3, wifiESSID, wifiPassword, dccex, port);
|
||||
}
|
||||
#endif
|
||||
#endif // >2
|
||||
#endif // >1
|
||||
#endif // WIFI_ON
|
||||
|
||||
// Responsibility 3: Start the DCC engine.
|
||||
// Note: this provides DCC with two motor drivers, main and prog, which handle the motor shield(s)
|
||||
|
@ -215,12 +123,14 @@ void loop()
|
|||
serialParser.loop(Serial);
|
||||
|
||||
// Responsibility 3: Optionally handle any incoming WiFi traffic
|
||||
#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560))
|
||||
#ifdef WIFI_ON
|
||||
WifiInterface::loop();
|
||||
#endif
|
||||
|
||||
// Optionally report any decrease in memory (will automatically trigger on first call)
|
||||
#if ENABLE_FREE_MEM_WARNING
|
||||
static int ramLowWatermark = 32767; // replaced on first loop
|
||||
|
||||
int freeNow = freeMemory();
|
||||
if (freeNow < ramLowWatermark)
|
||||
{
|
||||
|
|
17
DCCEX.h
Normal file
17
DCCEX.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
// This include is intended to visually simplify the .ino for the end users.
|
||||
// If there were any #ifdefs required they are much better handled in here.
|
||||
|
||||
#ifndef DCCEX_h
|
||||
#define DCCEX_h
|
||||
|
||||
#include "defines.h"
|
||||
#include "DCC.h"
|
||||
#include "DIAG.h"
|
||||
#include "DCCEXParser.h"
|
||||
#include "version.h"
|
||||
#include "WifiInterface.h"
|
||||
#include "EthernetInterface.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#endif
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* © 2020, Chris Harlow. All rights reserved.
|
||||
* © 2020, Harald Barth.
|
||||
*
|
||||
* This file is part of Asbelos DCC API
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -20,9 +21,6 @@
|
|||
#include "DCCEXParser.h"
|
||||
#include "DCC.h"
|
||||
#include "DCCWaveform.h"
|
||||
#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560))
|
||||
#include "WifiInterface.h"
|
||||
#endif
|
||||
#include "Turnouts.h"
|
||||
#include "Outputs.h"
|
||||
#include "Sensors.h"
|
||||
|
@ -156,10 +154,15 @@ int DCCEXParser::splitValues(int result[MAX_PARAMS], const byte *cmd)
|
|||
}
|
||||
|
||||
FILTER_CALLBACK DCCEXParser::filterCallback = 0;
|
||||
AT_COMMAND_CALLBACK DCCEXParser::atCommandCallback = 0;
|
||||
void DCCEXParser::setFilter(FILTER_CALLBACK filter)
|
||||
{
|
||||
filterCallback = filter;
|
||||
}
|
||||
void DCCEXParser::setAtCommandCallback(AT_COMMAND_CALLBACK callback)
|
||||
{
|
||||
atCommandCallback = callback;
|
||||
}
|
||||
|
||||
// See documentation on DCC class for info on this section
|
||||
void DCCEXParser::parse(Print *stream, byte *com, bool blocking)
|
||||
|
@ -391,11 +394,14 @@ void DCCEXParser::parse(Print *stream, byte *com, bool blocking)
|
|||
DIAG(F("Setting loco %d F%d %S"), p[0], p[1], p[2] ? F("ON") : F("OFF"));
|
||||
DCC::setFn(p[0], p[1], p[2] == 1);
|
||||
return;
|
||||
#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560))
|
||||
|
||||
case '+': // Complex Wifi interface command (not usual parse)
|
||||
WifiInterface::ATCommand(com);
|
||||
if (atCommandCallback) {
|
||||
atCommandCallback(com);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
default: //anything else will diagnose and drop out to <X>
|
||||
DIAG(F("\nOpcode=%c params=%d\n"), opcode, params);
|
||||
for (int i = 0; i < params; i++)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <Arduino.h>
|
||||
|
||||
typedef void (*FILTER_CALLBACK)(Print * stream, byte & opcode, byte & paramCount, int p[]);
|
||||
typedef void (*AT_COMMAND_CALLBACK)(const byte * command);
|
||||
|
||||
struct DCCEXParser
|
||||
{
|
||||
|
@ -29,6 +30,7 @@ struct DCCEXParser
|
|||
void parse(Print * stream, byte * command, bool blocking);
|
||||
void flush();
|
||||
static void setFilter(FILTER_CALLBACK filter);
|
||||
static void setAtCommandCallback(AT_COMMAND_CALLBACK filter);
|
||||
static const int MAX_PARAMS=10; // Must not exceed this
|
||||
|
||||
private:
|
||||
|
@ -59,6 +61,7 @@ struct DCCEXParser
|
|||
static void callback_Vbit(int result);
|
||||
static void callback_Vbyte(int result);
|
||||
static FILTER_CALLBACK filterCallback;
|
||||
static AT_COMMAND_CALLBACK atCommandCallback;
|
||||
static void funcmap(int cab, byte value, byte fstart, byte fstop);
|
||||
|
||||
};
|
||||
|
|
|
@ -30,7 +30,7 @@ const int MIN_ACK_PULSE_DURATION = 2000;
|
|||
const int MAX_ACK_PULSE_DURATION = 8500;
|
||||
|
||||
|
||||
const int PREAMBLE_BITS_MAIN = 20;
|
||||
const int PREAMBLE_BITS_MAIN = 16;
|
||||
const int PREAMBLE_BITS_PROG = 22;
|
||||
|
||||
|
||||
|
|
304
EthernetInterface.cpp
Normal file
304
EthernetInterface.cpp
Normal file
|
@ -0,0 +1,304 @@
|
|||
/*
|
||||
* © 2020,Gregor Baues, Chris Harlow. All rights reserved.
|
||||
*
|
||||
* This file is part of DCC-EX/CommandStation-EX
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Ethernet Interface added by Gregor Baues
|
||||
*/
|
||||
|
||||
#include "EthernetInterface.h"
|
||||
#include "DIAG.h"
|
||||
#include "StringFormatter.h"
|
||||
|
||||
//#include <SPI.h>
|
||||
#include <Ethernet.h>
|
||||
#include <EthernetUdp.h>
|
||||
|
||||
|
||||
// Support Functions
|
||||
/**
|
||||
* @brief Aquire IP Address from DHCP; if that fails try a statically configured address
|
||||
*
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool EthernetInterface::setupConnection()
|
||||
{
|
||||
|
||||
singleton=this;
|
||||
|
||||
DIAG(F("\nInitialize Ethernet with DHCP:"));
|
||||
server = EthernetServer(LISTEN_PORT); // Ethernet Server listening on default port LISTEN_PORT
|
||||
ip = IPAddress(IP_ADDRESS); // init with fixed IP address needed to get to the server
|
||||
connected = false; // Connection status
|
||||
streamer= new MemStream(buffer, MAX_ETH_BUFFER, MAX_ETH_BUFFER, true); // streamer who writes the results to the buffer
|
||||
|
||||
if (Ethernet.begin(EthernetInterface::mac) == 0)
|
||||
{
|
||||
DIAG(F("\nFailed to configure Ethernet using DHCP ... Trying with fixed IP"));
|
||||
Ethernet.begin(EthernetInterface::mac, EthernetInterface::ip); // default ip address
|
||||
|
||||
if (Ethernet.hardwareStatus() == EthernetNoHardware)
|
||||
{
|
||||
DIAG(F("\nEthernet shield was not found. Sorry, can't run without hardware. :("));
|
||||
return false;
|
||||
};
|
||||
if (Ethernet.linkStatus() == LinkOFF)
|
||||
{
|
||||
DIAG(F("\nEthernet cable is not connected."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ip = Ethernet.localIP(); // reassign the obtained ip address
|
||||
|
||||
DIAG(F("\nLocal IP address: [%d.%d.%d.%d]"), ip[0], ip[1], ip[2], ip[3]);
|
||||
DIAG(F("\nListening on port: [%d]"), port);
|
||||
dnsip = Ethernet.dnsServerIP();
|
||||
DIAG(F("\nDNS server IP address: [%d.%d.%d.%d] "), ip[0], ip[1], ip[2], ip[3]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles command requests recieved via UDP. UDP is a connection less, unreliable protocol as it doesn't maintain state but fast.
|
||||
*
|
||||
*/
|
||||
void EthernetInterface::udpHandler() {
|
||||
singleton->udpHandler2();
|
||||
}
|
||||
void EthernetInterface::udpHandler2()
|
||||
{
|
||||
|
||||
int packetSize = Udp.parsePacket();
|
||||
if (packetSize)
|
||||
{
|
||||
DIAG(F("\nReceived packet of size:[%d]\n"), packetSize);
|
||||
IPAddress remote = Udp.remoteIP();
|
||||
DIAG(F("From: [%d.%d.%d.%d:"), remote[0], remote[1], remote[2], remote[3]);
|
||||
char portBuffer[6];
|
||||
DIAG(F("%s]\n"), utoa(Udp.remotePort(), portBuffer, 10)); // DIAG has issues with unsigend int's so go through utoa
|
||||
|
||||
// read the packet into packetBufffer
|
||||
Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
|
||||
|
||||
DIAG(F("Command: [%s]\n"), packetBuffer);
|
||||
|
||||
streamer->flush();
|
||||
|
||||
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
|
||||
|
||||
ethParser.parse(streamer, (byte *)packetBuffer, true); // set to true so it is sync cf. WifiInterface
|
||||
|
||||
if (streamer->available() == 0)
|
||||
{
|
||||
DIAG(F("\nNo response\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// send the reply
|
||||
DIAG(F("Response: %s\n"), (char *)buffer);
|
||||
Udp.write((char *)buffer);
|
||||
Udp.endPacket();
|
||||
}
|
||||
|
||||
memset(packetBuffer, 0, UDP_TX_PACKET_MAX_SIZE); // reset PacktBuffer
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles command requests recieved via TCP. Supports up to the max# of simultaneous requests which is 8. The connection gets closed as soon as we finished processing
|
||||
*
|
||||
*/
|
||||
void EthernetInterface::tcpHandler()
|
||||
{
|
||||
singleton->tcpHandler2();
|
||||
}
|
||||
void EthernetInterface::tcpHandler2()
|
||||
{
|
||||
// get client from the server
|
||||
EthernetClient client = getServer().accept();
|
||||
|
||||
// check for new client
|
||||
if (client)
|
||||
{
|
||||
for (byte i = 0; i < MAX_SOCK_NUM; i++)
|
||||
{
|
||||
if (!clients[i])
|
||||
{
|
||||
// On accept() the EthernetServer doesn't track the client anymore
|
||||
// so we store it in our client array
|
||||
clients[i] = client;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for incoming data from all possible clients
|
||||
for (byte i = 0; i < MAX_SOCK_NUM; i++)
|
||||
{
|
||||
if (clients[i] && clients[i].available() > 0)
|
||||
{
|
||||
// read bytes from a client
|
||||
int count = clients[i].read(buffer, MAX_ETH_BUFFER);
|
||||
buffer[count] = '\0'; // terminate the string properly
|
||||
DIAG(F("\nReceived packet of size:[%d]\n"), count);
|
||||
DIAG(F("From Client #: [%d]\n"), i);
|
||||
DIAG(F("Command: [%s]\n"), buffer);
|
||||
|
||||
// as we use buffer for recv and send we have to reset the write position
|
||||
streamer->setBufferContentPosition(0, 0);
|
||||
|
||||
ethParser.parse(streamer, buffer, true); // set to true to that the execution in DCC is sync
|
||||
|
||||
if (streamer->available() == 0)
|
||||
{
|
||||
DIAG(F("No response\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[streamer->available()] = '\0'; // mark end of buffer, so it can be used as a string later
|
||||
DIAG(F("Response: %s\n"), (char *)buffer);
|
||||
if (clients[i].connected())
|
||||
{
|
||||
clients[i].write(buffer, streamer->available());
|
||||
}
|
||||
}
|
||||
}
|
||||
// stop any clients which disconnect
|
||||
for (byte i = 0; i < MAX_SOCK_NUM; i++)
|
||||
{
|
||||
if (clients[i] && !clients[i].connected())
|
||||
{
|
||||
DIAG(F("Disconnect client #%d \n"), i);
|
||||
clients[i].stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Class Functions
|
||||
/**
|
||||
* @brief Setup Ethernet Connection
|
||||
*
|
||||
* @param pt Protocol used
|
||||
* @param localPort Port number for the connection
|
||||
*/
|
||||
void EthernetInterface::setup(protocolType pt, uint16_t localPort)
|
||||
{
|
||||
DIAG(F("\n++++++ Ethernet Setup In Progress ++++++++\n"));
|
||||
port = localPort;
|
||||
if (setupConnection())
|
||||
{
|
||||
DIAG(F("\nProtocol: [%s]\n"), pt ? "UDP" : "TCP");
|
||||
switch (pt)
|
||||
{
|
||||
case UDP:
|
||||
{
|
||||
if (Udp.begin(localPort))
|
||||
{
|
||||
connected = true;
|
||||
protocolHandler = udpHandler;
|
||||
}
|
||||
else
|
||||
{
|
||||
DIAG(F("\nUDP client failed to start"));
|
||||
connected = false;
|
||||
}
|
||||
break;
|
||||
};
|
||||
case TCP:
|
||||
{
|
||||
Ethernet.begin(mac, ip);
|
||||
EthernetServer server(localPort);
|
||||
setServer(server);
|
||||
server.begin();
|
||||
connected = true;
|
||||
protocolHandler = tcpHandler;
|
||||
break;
|
||||
};
|
||||
default:
|
||||
{
|
||||
DIAG(F("Unkown Ethernet protocol; Setup failed"));
|
||||
connected = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
connected = false;
|
||||
};
|
||||
DIAG(F("\n++++++ Ethernet Setup %S ++++++++\n"), connected ? F("OK") : F("FAILED"));
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Setup Ethernet on default port and user choosen protocol
|
||||
*
|
||||
* @param pt Protocol UDP or TCP
|
||||
*/
|
||||
void EthernetInterface::setup(protocolType pt)
|
||||
{
|
||||
setup(pt, LISTEN_PORT);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Ethernet setup with defaults TCP / Listen Port
|
||||
*
|
||||
*/
|
||||
void EthernetInterface::setup()
|
||||
{
|
||||
setup(TCP, LISTEN_PORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Main loop for the EthernetInterface
|
||||
*
|
||||
*/
|
||||
void EthernetInterface::loop()
|
||||
{
|
||||
switch (Ethernet.maintain())
|
||||
{
|
||||
case 1:
|
||||
//renewed fail
|
||||
DIAG(F("\nError: renewed fail"));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
//renewed success
|
||||
DIAG(F("\nRenewed success: "));
|
||||
ip = Ethernet.localIP(); // reassign the obtained ip address
|
||||
DIAG(F("\nLocal IP address: [%d.%d.%d.%d]"),ip[0], ip[1], ip[2], ip[3]);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
//rebind fail
|
||||
DIAG(F("Error: rebind fail"));
|
||||
break;
|
||||
|
||||
case 4:
|
||||
//rebind success
|
||||
DIAG(F("Rebind success"));
|
||||
ip = Ethernet.localIP(); // reassign the obtained ip address
|
||||
DIAG(F("\nLocal IP address: [%d.%d.%d.%d]"), ip[0], ip[1], ip[2], ip[3]);
|
||||
break;
|
||||
|
||||
default:
|
||||
//nothing happened
|
||||
break;
|
||||
}
|
||||
protocolHandler();
|
||||
}
|
107
EthernetInterface.h
Normal file
107
EthernetInterface.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* © 2020,Gregor Baues, Chris Harlow. All rights reserved.
|
||||
*
|
||||
* This file is part of DCC-EX/CommandStation-EX
|
||||
*
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Ethernet Interface added by Gregor Baues
|
||||
*/
|
||||
|
||||
#ifndef EthernetInterface_h
|
||||
#define EthernetInterface_h
|
||||
|
||||
#include "DCCEXParser.h"
|
||||
#include "MemStream.h"
|
||||
#include <Arduino.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <Ethernet.h>
|
||||
|
||||
/* some generated mac addresses as EthernetShields don't have one by default in HW.
|
||||
* Sometimes they come on a sticker on the EthernetShield then use this address otherwise
|
||||
* just choose one from below or generate one yourself. Only condition is that there is no
|
||||
* other device on your network with the same Mac address.
|
||||
*
|
||||
* 52:b8:8a:8e:ce:21
|
||||
* e3:e9:73:e1:db:0d
|
||||
* 54:2b:13:52:ac:0c
|
||||
* c2:d8:d4:7d:7c:cb
|
||||
* 86:cf:fa:9f:07:79
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Network Configuration
|
||||
*
|
||||
*/
|
||||
#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 IP_ADDRESS 10, 0, 0, 101 // Just in case we don't get an adress from DHCP try a static one; make sure
|
||||
// this one is not used elsewhere and corresponds to your network layout
|
||||
#define LISTEN_PORT 3366 // default listen port for the server
|
||||
#define MAX_ETH_BUFFER 250
|
||||
|
||||
typedef void (*HTTP_CALLBACK)(Print * stream, byte * cmd);
|
||||
|
||||
enum protocolType {
|
||||
TCP,
|
||||
UDP
|
||||
};
|
||||
|
||||
typedef void (*protocolCallback)();
|
||||
|
||||
class EthernetInterface {
|
||||
|
||||
private:
|
||||
EthernetServer server;
|
||||
|
||||
public:
|
||||
DCCEXParser ethParser;
|
||||
bool connected;
|
||||
byte mac[6];
|
||||
IPAddress ip;
|
||||
uint16_t port;
|
||||
IPAddress dnsip;
|
||||
|
||||
void setup(protocolType pt, uint16_t lp); // specific port nummber
|
||||
void setup(protocolType pt); // uses default port number
|
||||
void setup(); // all defaults (protocol/port)
|
||||
|
||||
protocolCallback protocolHandler;
|
||||
|
||||
void loop();
|
||||
|
||||
private:
|
||||
static EthernetInterface * singleton;
|
||||
|
||||
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; // buffer to hold incoming UDP packet,
|
||||
uint8_t buffer[MAX_ETH_BUFFER]; // buffer provided to the streamer to be filled with the reply (used by TCP also for the recv)
|
||||
MemStream * streamer; // streamer who writes the results to the buffer
|
||||
EthernetClient clients[MAX_SOCK_NUM]; // accept up to MAX_SOCK_NUM client connections at the same time; This depends on the chipset used on the Shield
|
||||
|
||||
bool setupConnection();
|
||||
static void udpHandler();
|
||||
static void tcpHandler();
|
||||
void udpHandler2();
|
||||
void tcpHandler2();
|
||||
EthernetUDP Udp;
|
||||
|
||||
EthernetServer getServer() {
|
||||
return server;
|
||||
};
|
||||
void setServer(EthernetServer s) {
|
||||
server = s;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
© 2020, Chris Harlow. All rights reserved.
|
||||
© 2020, Harald Barth.
|
||||
|
||||
This file is part of Asbelos DCC API
|
||||
This file is part of CommandStation-EX
|
||||
|
||||
This is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -17,8 +18,8 @@
|
|||
along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "WifiInterface.h" /* config.h and defines.h included here */
|
||||
#include <avr/pgmspace.h>
|
||||
#include "WifiInterface.h"
|
||||
#include "DIAG.h"
|
||||
#include "StringFormatter.h"
|
||||
#include "WiThrottle.h"
|
||||
|
@ -39,7 +40,7 @@ unsigned long WifiInterface::loopTimeoutStart = 0;
|
|||
int WifiInterface::datalength = 0;
|
||||
int WifiInterface::connectionId;
|
||||
byte WifiInterface::buffer[MAX_WIFI_BUFFER+1];
|
||||
MemStream WifiInterface::streamer(buffer, MAX_WIFI_BUFFER);
|
||||
MemStream * WifiInterface::streamer;
|
||||
Stream * WifiInterface::wifiStream = NULL;
|
||||
HTTP_CALLBACK WifiInterface::httpCallback = 0;
|
||||
|
||||
|
@ -58,6 +59,8 @@ bool WifiInterface::setup(Stream & setupStream, const __FlashStringHelper* SSid
|
|||
StringFormatter::send(wifiStream, F("ATE0\r\n")); // turn off the echo
|
||||
checkForOK(200, OK_SEARCH, true);
|
||||
}
|
||||
streamer=new MemStream(buffer, MAX_WIFI_BUFFER);
|
||||
parser.setAtCommandCallback(ATCommand);
|
||||
|
||||
DIAG(F("\n++ Wifi Setup %S ++\n"), connected ? F("OK") : F("FAILED"));
|
||||
return connected;
|
||||
|
@ -298,15 +301,15 @@ void WifiInterface::loop() {
|
|||
case 6: // reading for length
|
||||
if (ch == ':') loopstate = (datalength == 0) ? 99 : 7; // 99 is getout without reading next char
|
||||
else datalength = datalength * 10 + (ch - '0');
|
||||
streamer.flush(); // basically sets write point at start of buffer
|
||||
streamer->flush(); // basically sets write point at start of buffer
|
||||
break;
|
||||
case 7: // reading data
|
||||
streamer.write(ch); // NOTE: The MemStream will throw away bytes that do not fit in the buffer.
|
||||
streamer->write(ch); // NOTE: The MemStream will throw away bytes that do not fit in the buffer.
|
||||
// This protects against buffer overflows even with things as innocent
|
||||
// as a browser which send massive, irrlevent HTTP headers.
|
||||
datalength--;
|
||||
if (datalength == 0) {
|
||||
buffer[streamer.available()]='\0'; // mark end of buffer, so it can be used as a string later
|
||||
buffer[streamer->available()]='\0'; // mark end of buffer, so it can be used as a string later
|
||||
loopstate = 99;
|
||||
}
|
||||
break;
|
||||
|
@ -349,8 +352,8 @@ void WifiInterface::loop() {
|
|||
loopstate = 1;
|
||||
}
|
||||
if (ch == 'K') { // assume its in SEND OK
|
||||
if (Diag::WIFI) DIAG(F("\n\n Wifi BUSY RETRYING.. AT+CIPSEND=%d,%d\r\n"), connectionId, streamer.available());
|
||||
StringFormatter::send(wifiStream, F("AT+CIPSEND=%d,%d\r\n"), connectionId, streamer.available());
|
||||
if (Diag::WIFI) DIAG(F("\n\n Wifi BUSY RETRYING.. AT+CIPSEND=%d,%d\r\n"), connectionId, streamer->available());
|
||||
StringFormatter::send(wifiStream, F("AT+CIPSEND=%d,%d\r\n"), connectionId, streamer->available());
|
||||
loopTimeoutStart = millis();
|
||||
loopstate = 10; // non-blocking loop waits for > before sending
|
||||
break;
|
||||
|
@ -363,7 +366,7 @@ void WifiInterface::loop() {
|
|||
// AT this point we have read an incoming message into the buffer
|
||||
|
||||
if (Diag::WIFI) DIAG(F("\n%l Wifi(%d)<-[%e]\n"), millis(),connectionId, buffer);
|
||||
streamer.setBufferContentPosition(0, 0); // reset write position to start of buffer
|
||||
streamer->setBufferContentPosition(0, 0); // reset write position to start of buffer
|
||||
// SIDE EFFECT WARNING:::
|
||||
// We know that parser will read the entire buffer before starting to write to it.
|
||||
// Otherwise we would have to copy the buffer elsewhere and RAM is in short supply.
|
||||
|
@ -372,18 +375,18 @@ void WifiInterface::loop() {
|
|||
|
||||
// Intercept HTTP requests
|
||||
if (isHTTP()) {
|
||||
if (httpCallback) httpCallback(&streamer, buffer);
|
||||
if (httpCallback) httpCallback(streamer, buffer);
|
||||
else {
|
||||
StringFormatter::send(streamer, F("HTTP/1.1 404 Not Found\nContent-Type: text/html\nConnnection: close\n\n"));
|
||||
StringFormatter::send(streamer, F("<html><body>This is <b>not</b> a web server.<br/></body></html>"));
|
||||
}
|
||||
closeAfter = true;
|
||||
}
|
||||
else if (buffer[0] == '<') parser.parse(&streamer, buffer, true); // tell JMRI parser that ACKS are blocking because we can't handle the async
|
||||
else if (buffer[0] == '<') parser.parse(streamer, buffer, true); // tell JMRI parser that ACKS are blocking because we can't handle the async
|
||||
|
||||
else WiThrottle::getThrottle(connectionId)->parse(streamer, buffer);
|
||||
else WiThrottle::getThrottle(connectionId)->parse(*streamer, buffer);
|
||||
|
||||
if (streamer.available() == 0) {
|
||||
if (streamer->available() == 0) {
|
||||
// No reply
|
||||
if (closeAfter) {
|
||||
if (Diag::WIFI) DIAG(F("AT+CIPCLOSE=%d\r\n"), connectionId);
|
||||
|
@ -393,10 +396,10 @@ void WifiInterface::loop() {
|
|||
return;
|
||||
}
|
||||
// prepare to send reply
|
||||
buffer[streamer.available()]='\0'; // mark end of buffer, so it can be used as a string later
|
||||
if (Diag::WIFI) DIAG(F("%l WiFi(%d)->[%e] l(%d)\n"), millis(), connectionId, buffer, streamer.available());
|
||||
if (Diag::WIFI) DIAG(F("AT+CIPSEND=%d,%d\r\n"), connectionId, streamer.available());
|
||||
StringFormatter::send(wifiStream, F("AT+CIPSEND=%d,%d\r\n"), connectionId, streamer.available());
|
||||
buffer[streamer->available()]='\0'; // mark end of buffer, so it can be used as a string later
|
||||
if (Diag::WIFI) DIAG(F("%l WiFi(%d)->[%e] l(%d)\n"), millis(), connectionId, buffer, streamer->available());
|
||||
if (Diag::WIFI) DIAG(F("AT+CIPSEND=%d,%d\r\n"), connectionId, streamer->available());
|
||||
StringFormatter::send(wifiStream, F("AT+CIPSEND=%d,%d\r\n"), connectionId, streamer->available());
|
||||
loopTimeoutStart = millis();
|
||||
loopstate = 10; // non-blocking loop waits for > before sending
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* © 2020, Chris Harlow. All rights reserved.
|
||||
* © 2020, Harald Barth.
|
||||
*
|
||||
* This file is part of Asbelos DCC API
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -16,12 +17,10 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WifiInterface_h
|
||||
#define WifiInterface_h
|
||||
#include "DCCEXParser.h"
|
||||
#include "MemStream.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
|
@ -53,7 +52,6 @@ private:
|
|||
static unsigned long loopTimeoutStart;
|
||||
static const byte MAX_WIFI_BUFFER = 250;
|
||||
static byte buffer[MAX_WIFI_BUFFER + 1];
|
||||
static MemStream streamer;
|
||||
static MemStream * streamer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,23 +15,18 @@ The configuration file for DCC++ EX Command Station
|
|||
// the correct resistor could damage the sense pin on your Arduino or destroy
|
||||
// the device.
|
||||
//
|
||||
// DEFINE MOTOR_SHIELD_TYPE ACCORDING TO THE FOLLOWING TABLE:
|
||||
// DEFINE MOTOR_SHIELD_TYPE BELOW ACCORDING TO THE FOLLOWING TABLE:
|
||||
//
|
||||
// STANDARD_MOTOR_SHIELD : Arduino Motor shield Rev3 based on the L298 with 18V 2A per channel
|
||||
// POLOLU_MOTOR_SHIELD : Pololu MC33926 Motor Driver (not recommended for prog track)
|
||||
// FUNDUMOTO_SHIELD : Fundumoto Shield, no current sensing (not recommended, no short protection)
|
||||
// FIREBOX_MK1 : The Firebox MK1
|
||||
// FIREBOX_MK1S : The Firebox MK1S
|
||||
// |
|
||||
// +-----------------------v
|
||||
//
|
||||
// STANDARD_MOTOR_SHIELD = ARDUINO MOTOR SHIELD (MAX 18V/2A PER CHANNEL) Arduino Motor shield Rev3 based on the L298
|
||||
// POLOLU_MOTOR_SHIELD = POLOLU MC33926 MOTOR SHIELD (MAX 28V/2.5 PER CHANNEL) Pololu MC33926 Motor Driver (shield or carrier)
|
||||
// FUNDUMOTO_SHIELD = FunduMoto Motor Shield
|
||||
// FIREBOX_MK1 = Firebox MK1
|
||||
// FIREBOX_MK1S = Firebox MK1S
|
||||
|
||||
|
||||
#define MOTOR_SHIELD_TYPE STANDARD_MOTOR_SHIELD
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DEFINE PROGRAM TRACK CURRENT LIMIT IN MILLIAMPS
|
||||
|
||||
#define TRIP_CURRENT_PROG 250
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The IP port to talk to a WIFI or Ethernet shield.
|
||||
|
@ -57,7 +52,6 @@ The configuration file for DCC++ EX Command Station
|
|||
//
|
||||
// DEFINE STATIC IP ADDRESS *OR* COMMENT OUT TO USE DHCP
|
||||
//
|
||||
|
||||
//#define IP_ADDRESS { 192, 168, 1, 200 }
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -67,60 +61,9 @@ The configuration file for DCC++ EX Command Station
|
|||
// Uncomment to use with Ethernet Shields
|
||||
//
|
||||
// NOTE: This is not used with ESP8266 WiFi modules.
|
||||
|
||||
//
|
||||
// #define MAC_ADDRESS { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF }
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Allows using a pin as a trigger for a scope or analyzer so we can capture only
|
||||
// the important parts of the data stream
|
||||
//
|
||||
// USE_TRIGGERPIN: Enable code that switches the trigger pin on and off at end
|
||||
// of the preamble. This takes some clock cycles in the
|
||||
// interrupt routine for the main track.
|
||||
// USE_TRIGGERPIN_PER_BIT: As above but for every bit. This only makes sense
|
||||
// if USE_TRIGGERPIN is set.
|
||||
//
|
||||
// The value of the TRIGGERPIN is defined in DCCppEX.h because it might
|
||||
// be board specific
|
||||
//
|
||||
//#define USE_TRIGGERPIN
|
||||
//#define USE_TRIGGERPIN_PER_BIT
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Define only of you need the store to EEPROM feature. This takes RAM and
|
||||
// you may need to use less MAX_MAIN_REGISTERS to compensate (at least on the UNO)
|
||||
|
||||
#define EESTORE
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This shows the status and version at startup. This takes RAM. You can comment
|
||||
// this line if you need to increase MAX_MAIN_REGISTERS(at least on the UNO)
|
||||
|
||||
#define SHOWCONFIG
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This is different from the above config display which only shows one line at startup
|
||||
// This defines a pin that when jumpered to ground before powering up the Arduinio,
|
||||
// will display more detailed settings for diagnostics. You must remove the jumper and
|
||||
// restart the Arduino to return to normal operation
|
||||
|
||||
#define SHOW_CONFIG_DETAIL_PIN A2
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PREAMBLE_MAIN: Length of the preamble on the main track. Per standard this should
|
||||
// be at least 14 bits but if some equipment wants to insert a RailCom
|
||||
// cutout this should be at least 16 bits.
|
||||
// PERAMBLE_PROG: Length of the preamble on the programming track. Per standard this
|
||||
// should be at least 22 bits
|
||||
|
||||
#define PREAMBLE_MAIN 16 // TODO: Finish configurable preamble code
|
||||
#define PREAMBLE_PROG 22
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DEFINE LCD SCREEN USAGE BY THE BASE STATION
|
||||
|
|
45
defines.h
Normal file
45
defines.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
© 2020, Harald Barth.
|
||||
|
||||
This file is part of CommandStation-EX
|
||||
|
||||
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/>.
|
||||
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WIFI_ON: All prereqs for running with WIFI are met
|
||||
//
|
||||
#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560))
|
||||
#define WIFI_ON
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This defines the speed at which the Arduino will communicate with the ESP8266 module.
|
||||
// Currently only devices which can communicate at 115200 are supported.
|
||||
//
|
||||
#define WIFI_SERIAL_LINK_SPEED 115200
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Figure out number of serial ports depending on hardware
|
||||
//
|
||||
#if (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560))
|
||||
#define NUM_SERIAL 3
|
||||
#endif
|
||||
#ifndef NUM_SERIAL
|
||||
#define NUM_SERIAL 1
|
||||
#endif
|
10
objdump.bat
10
objdump.bat
|
@ -1,12 +1,14 @@
|
|||
ECHO ON
|
||||
FOR /F "delims=" %%i IN ('dir %TMP%\arduino_build_* /b /ad-h /t:c /od') DO SET a=%%i
|
||||
echo Most recent subfolder: %a% >%TMP%\OBJDUMP_%a%.txt
|
||||
avr-objdump --private=mem-usage %TMP%\%a%\CommandStation-EX.ino.elf >>%TMP%\OBJDUMP_%a%.txt
|
||||
SET ELF=%TMP%\%a%\CommandStation-EX.ino.elf
|
||||
|
||||
avr-objdump --private=mem-usage %ELF% >>%TMP%\OBJDUMP_%a%.txt
|
||||
ECHO ++++++++++++++++++++++++++++++++++ >>%TMP%\OBJDUMP_%a%.txt
|
||||
avr-objdump -x -C %TMP%\%a%\CommandStation-EX.ino.elf | find ".text" | sort /+25 /R >>%TMP%\OBJDUMP_%a%.txt
|
||||
avr-objdump -x -C %ELF% | find ".text" | sort /+25 /R >>%TMP%\OBJDUMP_%a%.txt
|
||||
ECHO ++++++++++++++++++++++++++++++++++ >>%TMP%\OBJDUMP_%a%.txt
|
||||
avr-objdump -x -C %TMP%\%a%\CommandStation-EX.ino.elf | find ".data" | sort /+25 /R >>%TMP%\OBJDUMP_%a%.txt
|
||||
avr-objdump -x -C %ELF% | find ".data" | sort /+25 /R >>%TMP%\OBJDUMP_%a%.txt
|
||||
ECHO ++++++++++++++++++++++++++++++++++ >>%TMP%\OBJDUMP_%a%.txt
|
||||
avr-objdump -x -C %TMP%\%a%\CommandStation-EX.ino.elf | find ".bss" | sort /+25 /R >>%TMP%\OBJDUMP_%a%.txt
|
||||
avr-objdump -x -C %ELF% | find ".bss" | sort /+25 /R >>%TMP%\OBJDUMP_%a%.txt
|
||||
notepad %TMP%\OBJDUMP_%a%.txt
|
||||
EXIT
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
ARDUINOBIN=$(ls -l $(type -p arduino)| awk '{print $NF ; exit 0}')
|
||||
PATH=$(dirname "$ARDUINOBIN")/hardware/tools/avr/bin:$PATH
|
||||
|
||||
avr-objdump --private=mem-usage /tmp/arduino_build_233823/Blinkhabaplus.ino.elf
|
||||
LASTBUILD=$(ls -tr /tmp/arduino_build_*/*.ino.elf | tail -1)
|
||||
avr-objdump --private=mem-usage "$LASTBUILD"
|
||||
|
||||
for segment in .text .data .bss ; do
|
||||
echo '++++++++++++++++++++++++++++++++++'
|
||||
avr-objdump -x -C /tmp/arduino_build_233823/Blinkhabaplus.ino.elf | awk '$2 == "'$segment'" && $3 != 0 {print $3,$2} ; $4 == "'$segment'" && $5 != 0 { print $5,$6}' | sort -r
|
||||
avr-objdump -x -C "$LASTBUILD" | awk '$2 == "'$segment'" && $3 != 0 {print $3,$2} ; $4 == "'$segment'" && $5 != 0 { print $5,$6}' | sort -r
|
||||
done
|
||||
|
|
Loading…
Reference in New Issue
Block a user