mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-12-23 12:51:24 +01:00
Merge branch 'TM_nofloat' into TM-mergetest
This commit is contained in:
commit
7fba96417f
@ -30,16 +30,29 @@
|
||||
#include "DCC.h"
|
||||
#include "TrackManager.h"
|
||||
|
||||
#if defined(BIG_MEMORY) | defined(WIFI_ON) | defined(ETHERNET_ON)
|
||||
// This section of CommandDistributor is simply not relevant on a uno or similar
|
||||
const byte NO_CLIENT=255;
|
||||
|
||||
RingStream * CommandDistributor::ring=0;
|
||||
byte CommandDistributor::ringClient=NO_CLIENT;
|
||||
CommandDistributor::clientType CommandDistributor::clients[8]={
|
||||
NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE};
|
||||
RingStream * CommandDistributor::broadcastBufferWriter=new RingStream(100);
|
||||
#ifdef BIG_RAM
|
||||
// use a buffer to allow broadcast
|
||||
#define BUFFER broadcastBufferWriter
|
||||
#define FLUSH broadcastBufferWriter->flush();
|
||||
#define SHOVE(type) broadcastToClients(type);
|
||||
StringBuffer * CommandDistributor::broadcastBufferWriter=new StringBuffer();
|
||||
#else
|
||||
// on a UNO/NANO write direct to Serial and ignore flush/shove
|
||||
#define BUFFER &Serial
|
||||
#define FLUSH
|
||||
#define SHOVE(type)
|
||||
#endif
|
||||
|
||||
#ifdef CD_HANDLE_RING
|
||||
// wifi or ethernet ring streams with multiple client types
|
||||
RingStream * CommandDistributor::ring=0;
|
||||
byte CommandDistributor::ringClient=NO_CLIENT;
|
||||
CommandDistributor::clientType CommandDistributor::clients[8]={
|
||||
NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE};
|
||||
|
||||
// Parse is called by Withrottle or Ethernet interface to determine which
|
||||
// protocol the client is using and call the appropriate part of dcc++Ex
|
||||
void CommandDistributor::parse(byte clientId,byte * buffer, RingStream * stream) {
|
||||
ring=stream;
|
||||
ringClient=stream->peekTargetMark();
|
||||
@ -56,15 +69,15 @@ void CommandDistributor::parse(byte clientId,byte * buffer, RingStream * stream
|
||||
void CommandDistributor::forget(byte clientId) {
|
||||
clients[clientId]=NONE_TYPE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void CommandDistributor::broadcast(bool includeWithrottleClients) {
|
||||
broadcastBufferWriter->write((byte)'\0');
|
||||
// This will not be called on a uno
|
||||
void CommandDistributor::broadcastToClients(clientType type) {
|
||||
|
||||
/* Boadcast to Serials */
|
||||
SerialManager::broadcast(broadcastBufferWriter);
|
||||
if (type==COMMAND_TYPE) SerialManager::broadcast(broadcastBufferWriter->getString());
|
||||
|
||||
#if defined(WIFI_ON) | defined(ETHERNET_ON)
|
||||
#ifdef CD_HANDLE_RING
|
||||
// If we are broadcasting from a wifi/eth process we need to complete its output
|
||||
// before merging broadcasts in the ring, then reinstate it in case
|
||||
// the process continues to output to its client.
|
||||
@ -72,49 +85,46 @@ void CommandDistributor::broadcast(bool includeWithrottleClients) {
|
||||
|
||||
/* loop through ring clients */
|
||||
for (byte clientId=0; clientId<sizeof(clients); clientId++) {
|
||||
if (clients[clientId]==NONE_TYPE) continue;
|
||||
if ( clients[clientId]==WITHROTTLE_TYPE && !includeWithrottleClients) continue;
|
||||
ring->mark(clientId);
|
||||
broadcastBufferWriter->printBuffer(ring);
|
||||
ring->commit();
|
||||
if (clients[clientId]==type) {
|
||||
ring->mark(clientId);
|
||||
ring->print(broadcastBufferWriter->getString());
|
||||
ring->commit();
|
||||
}
|
||||
}
|
||||
if (ringClient!=NO_CLIENT) ring->mark(ringClient);
|
||||
|
||||
#endif
|
||||
broadcastBufferWriter->flush();
|
||||
}
|
||||
#else
|
||||
// For a UNO/NANO we can broadcast direct to just one Serial instead of the ring
|
||||
// Redirect ring output ditrect to Serial
|
||||
#define broadcastBufferWriter &Serial
|
||||
// and ignore the internal broadcast call.
|
||||
void CommandDistributor::broadcast(bool includeWithrottleClients) {
|
||||
(void)includeWithrottleClients;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Public broadcast functions below
|
||||
void CommandDistributor::broadcastSensor(int16_t id, bool on ) {
|
||||
StringFormatter::send(broadcastBufferWriter,F("<%c %d>\n"), on?'Q':'q', id);
|
||||
broadcast(false);
|
||||
FLUSH
|
||||
StringFormatter::send(BUFFER,F("<%c %d>\n"), on?'Q':'q', id);
|
||||
SHOVE(COMMAND_TYPE)
|
||||
}
|
||||
|
||||
void CommandDistributor::broadcastTurnout(int16_t id, bool isClosed ) {
|
||||
// For DCC++ classic compatibility, state reported to JMRI is 1 for thrown and 0 for closed;
|
||||
// The string below contains serial and Withrottle protocols which should
|
||||
// be safe for both types.
|
||||
StringFormatter::send(broadcastBufferWriter,F("<H %d %d>\n"),id, !isClosed);
|
||||
#if defined(WIFI_ON) | defined(ETHERNET_ON)
|
||||
StringFormatter::send(broadcastBufferWriter,F("PTA%c%d\n"), isClosed?'2':'4', id);
|
||||
FLUSH
|
||||
StringFormatter::send(BUFFER,F("<H %d %d>\n"),id, !isClosed);
|
||||
SHOVE(COMMAND_TYPE)
|
||||
|
||||
#ifdef CD_HANDLE_RING
|
||||
FLUSH
|
||||
StringFormatter::send(BUFFER,F("PTA%c%d\n"), isClosed?'2':'4', id);
|
||||
SHOVE(WITHROTTLE_TYPE)
|
||||
#endif
|
||||
broadcast(true);
|
||||
}
|
||||
|
||||
void CommandDistributor::broadcastLoco(byte slot) {
|
||||
DCC::LOCO * sp=&DCC::speedTable[slot];
|
||||
StringFormatter::send(broadcastBufferWriter,F("<l %d %d %d %l>\n"),
|
||||
FLUSH
|
||||
StringFormatter::send(BUFFER,F("<l %d %d %d %l>\n"),
|
||||
sp->loco,slot,sp->speedCode,sp->functions);
|
||||
broadcast(false);
|
||||
#if defined(WIFI_ON) | defined(ETHERNET_ON)
|
||||
SHOVE(COMMAND_TYPE)
|
||||
#ifdef CD_HANDLE_RING
|
||||
WiThrottle::markForBroadcast(sp->loco);
|
||||
#endif
|
||||
}
|
||||
@ -130,14 +140,24 @@ void CommandDistributor::broadcastPower() {
|
||||
else if (main) reason=F(" MAIN");
|
||||
else if (prog) reason=F(" PROG");
|
||||
else state='0';
|
||||
|
||||
StringFormatter::send(broadcastBufferWriter,
|
||||
F("<p%c%S>\nPPA%c\n"),state,reason, main?'1':'0');
|
||||
LCD(2,F("Power %S%S"),state=='1'?F("On"):F("Off"),reason);
|
||||
broadcast(true);
|
||||
FLUSH
|
||||
StringFormatter::send(BUFFER,F("<p %c%S>\n"),state,reason);
|
||||
SHOVE(COMMAND_TYPE)
|
||||
#ifdef CD_HANDLE_RING
|
||||
FLUSH
|
||||
StringFormatter::send(BUFFER,F("PPA%c\n"), main?'1':'0');
|
||||
SHOVE(WITHROTTLE_TYPE)
|
||||
#endif
|
||||
LCD(2,F("Power %S%S"),state=='1'?F("On"):F("Off"),reason);
|
||||
}
|
||||
|
||||
void CommandDistributor::broadcastText(const FSH * msg) {
|
||||
StringFormatter::send(broadcastBufferWriter,F("%S"),msg);
|
||||
broadcast(false);
|
||||
FLUSH
|
||||
StringFormatter::send(BUFFER,F("%S"),msg);
|
||||
SHOVE(COMMAND_TYPE)
|
||||
#ifdef CD_HANDLE_RING
|
||||
FLUSH
|
||||
StringFormatter::send(BUFFER,F("Hm%S\n"), msg);
|
||||
SHOVE(WITHROTTLE_TYPE)
|
||||
#endif
|
||||
}
|
||||
|
@ -23,6 +23,13 @@
|
||||
#define CommandDistributor_h
|
||||
#include "DCCEXParser.h"
|
||||
#include "RingStream.h"
|
||||
#include "StringBuffer.h"
|
||||
#include "defines.h"
|
||||
|
||||
#if WIFI_ON | ETHERNET_ON
|
||||
// Command Distributor must handle a RingStream of clients
|
||||
#define CD_HANDLE_RING
|
||||
#endif
|
||||
|
||||
class CommandDistributor {
|
||||
|
||||
@ -35,14 +42,15 @@ public :
|
||||
static void broadcastText(const FSH * msg);
|
||||
static void forget(byte clientId);
|
||||
private:
|
||||
static void broadcast(bool includeWithrottleClients);
|
||||
static RingStream * ring;
|
||||
static RingStream * broadcastBufferWriter;
|
||||
static byte ringClient;
|
||||
|
||||
// each bit in broadcastlist = 1<<clientid
|
||||
enum clientType: byte {NONE_TYPE,COMMAND_TYPE,WITHROTTLE_TYPE};
|
||||
static clientType clients[8];
|
||||
enum clientType: byte {NONE_TYPE,COMMAND_TYPE,WITHROTTLE_TYPE};
|
||||
static void broadcastToClients(clientType type);
|
||||
static StringBuffer * broadcastBufferWriter;
|
||||
#ifdef CD_HANDLE_RING
|
||||
static RingStream * ring;
|
||||
static const byte NO_CLIENT=255;
|
||||
static byte ringClient;
|
||||
static clientType clients[8];
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1 +1 @@
|
||||
#define GITHUB_SHA "TM-PORTX-20220611"
|
||||
#define GITHUB_SHA "TM-PORTX-20220611-1"
|
||||
|
@ -88,16 +88,23 @@ MotorDriver::MotorDriver(VPIN power_pin, byte signal_pin, byte signal_pin2, int8
|
||||
pinMode(faultPin, INPUT);
|
||||
}
|
||||
|
||||
senseFactor=sense_factor;
|
||||
// This conversion performed at compile time so the remainder of the code never needs
|
||||
// float calculations or libraray code.
|
||||
senseFactorInternal=sense_factor * senseScale;
|
||||
tripMilliamps=trip_milliamps;
|
||||
rawCurrentTripValue=(int)(trip_milliamps / sense_factor);
|
||||
rawCurrentTripValue=mA2raw(trip_milliamps);
|
||||
|
||||
if (currentPin==UNUSED_PIN)
|
||||
DIAG(F("MotorDriver ** WARNING ** No current or short detection"));
|
||||
else
|
||||
else {
|
||||
DIAG(F("MotorDriver currentPin=A%d, senseOffset=%d, rawCurrentTripValue(relative to offset)=%d"),
|
||||
currentPin-A0, senseOffset,rawCurrentTripValue);
|
||||
|
||||
// self testing diagnostic for the non-float converters... may be removed when happy
|
||||
// DIAG(F("senseFactorInternal=%d raw2mA(1000)=%d mA2Raw(1000)=%d"),
|
||||
// senseFactorInternal, raw2mA(1000),mA2raw(1000));
|
||||
}
|
||||
|
||||
// prepare values for current detection
|
||||
sampleDelay = 0;
|
||||
lastSampleTaken = millis();
|
||||
@ -213,10 +220,10 @@ int MotorDriver::getCurrentRawInInterrupt() {
|
||||
}
|
||||
|
||||
unsigned int MotorDriver::raw2mA( int raw) {
|
||||
return (unsigned int)(raw * senseFactor);
|
||||
return (int32_t)raw * senseFactorInternal / senseScale;
|
||||
}
|
||||
int MotorDriver::mA2raw( unsigned int mA) {
|
||||
return (int)(mA / senseFactor);
|
||||
unsigned int MotorDriver::mA2raw( unsigned int mA) {
|
||||
return (int32_t)mA * senseScale / senseFactorInternal;
|
||||
}
|
||||
|
||||
void MotorDriver::getFastPin(const FSH* type,int pin, bool input, FASTPIN & result) {
|
||||
|
@ -113,9 +113,9 @@ class MotorDriver {
|
||||
virtual int getCurrentRaw();
|
||||
virtual int getCurrentRawInInterrupt();
|
||||
virtual unsigned int raw2mA( int raw);
|
||||
virtual int mA2raw( unsigned int mA);
|
||||
inline bool brakeCanPWM() {
|
||||
return ((brakePin!=UNUSED_PIN) && (digitalPinToTimer(brakePin)));
|
||||
virtual unsigned int mA2raw( unsigned int mA);
|
||||
}
|
||||
inline int getRawCurrentTripValue() {
|
||||
return rawCurrentTripValue;
|
||||
@ -142,7 +142,14 @@ class MotorDriver {
|
||||
FASTPIN fastSignalPin, fastSignalPin2, fastBrakePin,fastFaultPin;
|
||||
bool dualSignal; // true to use signalPin2
|
||||
bool invertBrake; // brake pin passed as negative means pin is inverted
|
||||
float senseFactor;
|
||||
|
||||
// Raw to milliamp conversion factors avoiding float data types.
|
||||
// Milliamps=rawADCreading * sensefactorInternal / senseScale
|
||||
//
|
||||
// senseScale is chosen as 256 to give enough scale for 2 decimal place
|
||||
// raw->mA conversion with an ultra fast optimised integer multiplication
|
||||
int senseFactorInternal; // set to senseFactor * senseScale
|
||||
static const int senseScale=256;
|
||||
int senseOffset;
|
||||
unsigned int tripMilliamps;
|
||||
int rawCurrentTripValue;
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "SerialManager.h"
|
||||
#include "DCCEXParser.h"
|
||||
|
||||
SerialManager * SerialManager::first=NULL;
|
||||
|
||||
SerialManager::SerialManager(Stream * myserial) {
|
||||
@ -49,11 +50,11 @@ void SerialManager::init() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void SerialManager::broadcast(RingStream * ring) {
|
||||
for (SerialManager * s=first;s;s=s->next) s->broadcast2(ring);
|
||||
void SerialManager::broadcast(char * stringBuffer) {
|
||||
for (SerialManager * s=first;s;s=s->next) s->broadcast2(stringBuffer);
|
||||
}
|
||||
void SerialManager::broadcast2(RingStream * ring) {
|
||||
ring->printBuffer(serial);
|
||||
void SerialManager::broadcast2(char * stringBuffer) {
|
||||
serial->print(stringBuffer);
|
||||
}
|
||||
|
||||
void SerialManager::loop() {
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "defines.h"
|
||||
#include "RingStream.h"
|
||||
|
||||
|
||||
#ifndef COMMAND_BUFFER_SIZE
|
||||
#define COMMAND_BUFFER_SIZE 100
|
||||
@ -33,13 +33,13 @@ class SerialManager {
|
||||
public:
|
||||
static void init();
|
||||
static void loop();
|
||||
static void broadcast(RingStream * ring);
|
||||
static void broadcast(char * stringBuffer);
|
||||
|
||||
private:
|
||||
static SerialManager * first;
|
||||
SerialManager(Stream * myserial);
|
||||
void loop2();
|
||||
void broadcast2(RingStream * ring);
|
||||
void broadcast2(char * stringBuffer);
|
||||
Stream * serial;
|
||||
SerialManager * next;
|
||||
byte bufferLength;
|
||||
|
45
StringBuffer.cpp
Normal file
45
StringBuffer.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* © 2022 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/>.
|
||||
*/
|
||||
|
||||
#include "StringBuffer.h"
|
||||
#include "DIAG.h"
|
||||
|
||||
StringBuffer::StringBuffer() {
|
||||
flush();
|
||||
};
|
||||
|
||||
char * StringBuffer::getString() {
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
void StringBuffer::flush() {
|
||||
_pos_write=0;
|
||||
_buffer[0]='\0';
|
||||
}
|
||||
|
||||
size_t StringBuffer::write(uint8_t b) {
|
||||
if (_pos_write>=buffer_max) return 0;
|
||||
_buffer[_pos_write] = b;
|
||||
++_pos_write;
|
||||
_buffer[_pos_write]='\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
38
StringBuffer.h
Normal file
38
StringBuffer.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* © 2022 Chris Harlow
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of DCC++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/>.
|
||||
*/
|
||||
|
||||
#ifndef StringBuffer_h
|
||||
#define StringBuffer_h
|
||||
#include <Arduino.h>
|
||||
|
||||
class StringBuffer : public Print {
|
||||
public:
|
||||
StringBuffer();
|
||||
// Override Print default
|
||||
virtual size_t write(uint8_t b);
|
||||
void flush();
|
||||
char * getString();
|
||||
private:
|
||||
static const int buffer_max=64; // enough for long text msgs to throttles
|
||||
int16_t _pos_write;
|
||||
char _buffer[buffer_max+1];
|
||||
};
|
||||
|
||||
#endif
|
@ -104,7 +104,7 @@ void StringFormatter::send2(Print * stream,const FSH* format, va_list args) {
|
||||
case 'b': stream->print(va_arg(args, int), BIN); break;
|
||||
case 'o': stream->print(va_arg(args, int), OCT); break;
|
||||
case 'x': stream->print(va_arg(args, int), HEX); break;
|
||||
case 'f': stream->print(va_arg(args, double), 2); break;
|
||||
//case 'f': stream->print(va_arg(args, double), 2); break;
|
||||
//format width prefix
|
||||
case '-':
|
||||
formatLeft=true;
|
||||
|
@ -4,8 +4,10 @@
|
||||
#include "StringFormatter.h"
|
||||
|
||||
|
||||
#define VERSION "4.2.0 rc1"
|
||||
#define VERSION "4.2.0 rc2"
|
||||
// 4.2.0 Track Manager additions:
|
||||
// Broadcast improvements to separate <> and Withrottle responses
|
||||
// Float eliminated saving >1.5kb PROGMEM and speed.
|
||||
// SET_TRACK(track,mode) Functions (A-H, MAIN|PROG|DC|DCX|OFF)
|
||||
// New DC track function and DCX reverse polarity function
|
||||
// TrackManager DCC & DC up to 8 Districts Architecture
|
||||
|
Loading…
Reference in New Issue
Block a user