mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-23 16:16:13 +01:00
Compare commits
14 Commits
235c861395
...
e236c150f2
Author | SHA1 | Date | |
---|---|---|---|
|
e236c150f2 | ||
|
3b162996ad | ||
|
fb414a7a50 | ||
|
818e05b425 | ||
|
c5168f030f | ||
|
3da4cb0961 | ||
|
0bfc228d3c | ||
|
9b17aaf53e | ||
|
579931a885 | ||
|
7b5e2b41da | ||
|
4bdc4b7079 | ||
|
5fde819fa2 | ||
|
b8d1c682ea | ||
|
fb8cca8d35 |
|
@ -181,7 +181,20 @@ void CommandDistributor::setClockTime(int16_t clocktime, int8_t clockrate, byte
|
||||||
case 1:
|
case 1:
|
||||||
if (clocktime != lastclocktime){
|
if (clocktime != lastclocktime){
|
||||||
// CAH. DIAG removed because LCD does it anyway.
|
// CAH. DIAG removed because LCD does it anyway.
|
||||||
LCD(6,F("Clk Time:%d Sp %d"), clocktime, clockrate);
|
|
||||||
|
#ifndef FASTCLOCK_READABLE
|
||||||
|
LCD(6,F("Clk Time: %d Sp %d"), clocktime, clockrate);
|
||||||
|
#else
|
||||||
|
// Make Time readable
|
||||||
|
int hours = clocktime / 60;
|
||||||
|
int minutes = clocktime - (hours * 60);
|
||||||
|
int hoursH = hours / 10;
|
||||||
|
int hoursL = hours - (hoursH * 10);
|
||||||
|
int minutesH = minutes / 10;
|
||||||
|
int minutesL = minutes - (minutesH * 10);
|
||||||
|
LCD(6,F("Clk Time: %d%d:%d%d Sp %d"), hoursH, hoursL, minutesH, minutesL, clockrate);
|
||||||
|
#endif
|
||||||
|
|
||||||
// look for an event for this time
|
// look for an event for this time
|
||||||
RMFT2::clockEvent(clocktime,1);
|
RMFT2::clockEvent(clocktime,1);
|
||||||
// Now tell everyone else what the time is.
|
// Now tell everyone else what the time is.
|
||||||
|
|
|
@ -259,8 +259,9 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RMFT2::setTurnoutHiddenState(Turnout * t) {
|
void RMFT2::setTurnoutHiddenState(Turnout * t) {
|
||||||
// turnout descriptions are in low flash F strings
|
// turnout descriptions are in low flash F strings
|
||||||
t->setHidden(GETFLASH(getTurnoutDescription(t->getId()))==0x01);
|
const FSH *desc = getTurnoutDescription(t->getId());
|
||||||
|
if (desc) t->setHidden(GETFLASH(desc)==0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
char RMFT2::getRouteType(int16_t id) {
|
char RMFT2::getRouteType(int16_t id) {
|
||||||
|
|
|
@ -48,6 +48,10 @@
|
||||||
static const FSH * guessI2CDeviceType(uint8_t address) {
|
static const FSH * guessI2CDeviceType(uint8_t address) {
|
||||||
if (address >= 0x20 && address <= 0x26)
|
if (address >= 0x20 && address <= 0x26)
|
||||||
return F("GPIO Expander");
|
return F("GPIO Expander");
|
||||||
|
#ifdef FAST_CLOCK_I2C
|
||||||
|
else if (address == FAST_CLOCK_I2C)
|
||||||
|
return F("Fast Clock");
|
||||||
|
#endif
|
||||||
else if (address == 0x27)
|
else if (address == 0x27)
|
||||||
return F("GPIO Expander or LCD Display");
|
return F("GPIO Expander or LCD Display");
|
||||||
else if (address == 0x29)
|
else if (address == 0x29)
|
||||||
|
@ -363,4 +367,4 @@ void I2CAddress::toHex(const uint8_t value, char *buffer) {
|
||||||
|
|
||||||
/* static */ bool I2CAddress::_addressWarningDone = false;
|
/* static */ bool I2CAddress::_addressWarningDone = false;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
12
IODevice.cpp
12
IODevice.cpp
|
@ -27,6 +27,12 @@
|
||||||
#include "IO_MCP23017.h"
|
#include "IO_MCP23017.h"
|
||||||
#include "DCCTimer.h"
|
#include "DCCTimer.h"
|
||||||
|
|
||||||
|
#if !defined(IO_NO_HAL)
|
||||||
|
#ifdef FAST_CLOCK_I2C
|
||||||
|
#include "IO_EXFastClock.h" // FastClock driver
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
|
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
|
||||||
#define USE_FAST_IO
|
#define USE_FAST_IO
|
||||||
#endif
|
#endif
|
||||||
|
@ -75,6 +81,11 @@ void IODevice::begin() {
|
||||||
} else {
|
} else {
|
||||||
DIAG(F("Default PCA9685 at I2C 0x41 disabled due to configured user device"));
|
DIAG(F("Default PCA9685 at I2C 0x41 disabled due to configured user device"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FAST_CLOCK_I2C
|
||||||
|
DIAG(F("EXFastClock::create"));
|
||||||
|
EXFastClock::create(FAST_CLOCK_I2C);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Predefine two MCP23017 module 0x20/0x21 if no conflicts
|
// Predefine two MCP23017 module 0x20/0x21 if no conflicts
|
||||||
// Allocates 32 pins 164-195
|
// Allocates 32 pins 164-195
|
||||||
|
@ -582,4 +593,3 @@ bool ArduinoPins::fastReadDigital(uint8_t pin) {
|
||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,12 +56,12 @@ static void create(I2CAddress i2cAddress) {
|
||||||
// XXXX change thistosave2 bytes
|
// XXXX change thistosave2 bytes
|
||||||
if (_checkforclock == 0) {
|
if (_checkforclock == 0) {
|
||||||
FAST_CLOCK_EXISTS = true;
|
FAST_CLOCK_EXISTS = true;
|
||||||
//DIAG(F("I2C Fast Clock found at %s"), i2cAddress.toString());
|
DIAG(F("I2C Fast Clock found at %s"), i2cAddress.toString());
|
||||||
new EXFastClock(i2cAddress);
|
new EXFastClock(i2cAddress);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
FAST_CLOCK_EXISTS = false;
|
FAST_CLOCK_EXISTS = false;
|
||||||
//DIAG(F("No Fast Clock found"));
|
DIAG(F("No Fast Clock found"));
|
||||||
LCD(6,F("CLOCK NOT FOUND"));
|
LCD(6,F("CLOCK NOT FOUND"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,8 @@ void _loop(unsigned long currentMicros) override{
|
||||||
if (FAST_CLOCK_EXISTS==true) {
|
if (FAST_CLOCK_EXISTS==true) {
|
||||||
uint8_t readBuffer[3];
|
uint8_t readBuffer[3];
|
||||||
byte a,b;
|
byte a,b;
|
||||||
#ifdef EXRAIL_ACTIVE
|
// I would like to use the FastClock without EXRAIL
|
||||||
|
// #ifdef EXRAIL_ACTIVE
|
||||||
I2CManager.read(_I2CAddress, readBuffer, 3);
|
I2CManager.read(_I2CAddress, readBuffer, 3);
|
||||||
// XXXX change this to save a few bytes
|
// XXXX change this to save a few bytes
|
||||||
a = readBuffer[0];
|
a = readBuffer[0];
|
||||||
|
@ -110,7 +111,7 @@ void _loop(unsigned long currentMicros) override{
|
||||||
// Clock interval is 60/ clockspeed i.e 60/b seconds
|
// Clock interval is 60/ clockspeed i.e 60/b seconds
|
||||||
delayUntil(currentMicros + ((60/b) * 1000000));
|
delayUntil(currentMicros + ((60/b) * 1000000));
|
||||||
|
|
||||||
#endif
|
// #endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* © 2022, Peter Cole. All rights reserved.
|
* © 2022, Peter Cole. All rights reserved.
|
||||||
|
* © 2024, Harald Barth. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of EX-CommandStation
|
* This file is part of EX-CommandStation
|
||||||
*
|
*
|
||||||
|
@ -98,34 +99,53 @@ private:
|
||||||
_numAnaloguePins = receiveBuffer[2];
|
_numAnaloguePins = receiveBuffer[2];
|
||||||
|
|
||||||
// See if we already have suitable buffers assigned
|
// See if we already have suitable buffers assigned
|
||||||
size_t digitalBytesNeeded = (_numDigitalPins + 7) / 8;
|
if (_numDigitalPins>0) {
|
||||||
if (_digitalPinBytes < digitalBytesNeeded) {
|
size_t digitalBytesNeeded = (_numDigitalPins + 7) / 8;
|
||||||
// Not enough space, free any existing buffer and allocate a new one
|
if (_digitalPinBytes < digitalBytesNeeded) {
|
||||||
if (_digitalPinBytes > 0) free(_digitalInputStates);
|
// Not enough space, free any existing buffer and allocate a new one
|
||||||
_digitalInputStates = (byte*) calloc(_digitalPinBytes, 1);
|
if (_digitalPinBytes > 0) free(_digitalInputStates);
|
||||||
_digitalPinBytes = digitalBytesNeeded;
|
if ((_digitalInputStates = (byte*) calloc(digitalBytesNeeded, 1)) != NULL) {
|
||||||
}
|
_digitalPinBytes = digitalBytesNeeded;
|
||||||
size_t analogueBytesNeeded = _numAnaloguePins * 2;
|
} else {
|
||||||
if (_analoguePinBytes < analogueBytesNeeded) {
|
DIAG(F("EX-IOExpander I2C:%s ERROR alloc %d bytes"), _I2CAddress.toString(), digitalBytesNeeded);
|
||||||
// Free any existing buffers and allocate new ones.
|
_deviceState = DEVSTATE_FAILED;
|
||||||
if (_analoguePinBytes > 0) {
|
_digitalPinBytes = 0;
|
||||||
free(_analogueInputBuffer);
|
return;
|
||||||
free(_analogueInputStates);
|
}
|
||||||
free(_analoguePinMap);
|
|
||||||
}
|
}
|
||||||
_analogueInputStates = (uint8_t*) calloc(analogueBytesNeeded, 1);
|
|
||||||
_analogueInputBuffer = (uint8_t*) calloc(analogueBytesNeeded, 1);
|
|
||||||
_analoguePinMap = (uint8_t*) calloc(_numAnaloguePins, 1);
|
|
||||||
_analoguePinBytes = analogueBytesNeeded;
|
|
||||||
}
|
}
|
||||||
} else {
|
if (_numAnaloguePins>0) {
|
||||||
DIAG(F("EX-IOExpander I2C:%s ERROR configuring device"), _I2CAddress.toString());
|
size_t analogueBytesNeeded = _numAnaloguePins * 2;
|
||||||
_deviceState = DEVSTATE_FAILED;
|
if (_analoguePinBytes < analogueBytesNeeded) {
|
||||||
return;
|
// Free any existing buffers and allocate new ones.
|
||||||
}
|
if (_analoguePinBytes > 0) {
|
||||||
}
|
free(_analogueInputBuffer);
|
||||||
// We now need to retrieve the analogue pin map
|
free(_analogueInputStates);
|
||||||
if (status == I2C_STATUS_OK) {
|
free(_analoguePinMap);
|
||||||
|
}
|
||||||
|
_analogueInputStates = (uint8_t*) calloc(analogueBytesNeeded, 1);
|
||||||
|
_analogueInputBuffer = (uint8_t*) calloc(analogueBytesNeeded, 1);
|
||||||
|
_analoguePinMap = (uint8_t*) calloc(_numAnaloguePins, 1);
|
||||||
|
if (_analogueInputStates != NULL &&
|
||||||
|
_analogueInputBuffer != NULL &&
|
||||||
|
_analoguePinMap != NULL) {
|
||||||
|
_analoguePinBytes = analogueBytesNeeded;
|
||||||
|
} else {
|
||||||
|
DIAG(F("EX-IOExpander I2C:%s ERROR alloc analog pin bytes"), _I2CAddress.toString());
|
||||||
|
_deviceState = DEVSTATE_FAILED;
|
||||||
|
_analoguePinBytes = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DIAG(F("EX-IOExpander I2C:%s ERROR configuring device"), _I2CAddress.toString());
|
||||||
|
_deviceState = DEVSTATE_FAILED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We now need to retrieve the analogue pin map if there are analogue pins
|
||||||
|
if (status == I2C_STATUS_OK && _numAnaloguePins>0) {
|
||||||
commandBuffer[0] = EXIOINITA;
|
commandBuffer[0] = EXIOINITA;
|
||||||
status = I2CManager.read(_I2CAddress, _analoguePinMap, _numAnaloguePins, commandBuffer, 1);
|
status = I2CManager.read(_I2CAddress, _analoguePinMap, _numAnaloguePins, commandBuffer, 1);
|
||||||
}
|
}
|
||||||
|
@ -239,7 +259,7 @@ private:
|
||||||
|
|
||||||
// If we're not doing anything now, check to see if a new input transfer is due.
|
// If we're not doing anything now, check to see if a new input transfer is due.
|
||||||
if (_readState == RDS_IDLE) {
|
if (_readState == RDS_IDLE) {
|
||||||
if (currentMicros - _lastDigitalRead > _digitalRefresh) { // Delay for digital read refresh
|
if (_numDigitalPins>0 && currentMicros - _lastDigitalRead > _digitalRefresh) { // Delay for digital read refresh
|
||||||
// Issue new read request for digital states. As the request is non-blocking, the buffer has to
|
// Issue new read request for digital states. As the request is non-blocking, the buffer has to
|
||||||
// be allocated from heap (object state).
|
// be allocated from heap (object state).
|
||||||
_readCommandBuffer[0] = EXIORDD;
|
_readCommandBuffer[0] = EXIORDD;
|
||||||
|
@ -247,7 +267,7 @@ private:
|
||||||
// non-blocking read
|
// non-blocking read
|
||||||
_lastDigitalRead = currentMicros;
|
_lastDigitalRead = currentMicros;
|
||||||
_readState = RDS_DIGITAL;
|
_readState = RDS_DIGITAL;
|
||||||
} else if (currentMicros - _lastAnalogueRead > _analogueRefresh) { // Delay for analogue read refresh
|
} else if (_numAnaloguePins>0 && currentMicros - _lastAnalogueRead > _analogueRefresh) { // Delay for analogue read refresh
|
||||||
// Issue new read for analogue input states
|
// Issue new read for analogue input states
|
||||||
_readCommandBuffer[0] = EXIORDAN;
|
_readCommandBuffer[0] = EXIORDAN;
|
||||||
I2CManager.read(_I2CAddress, _analogueInputBuffer,
|
I2CManager.read(_I2CAddress, _analogueInputBuffer,
|
||||||
|
@ -362,14 +382,14 @@ private:
|
||||||
uint8_t _minorVer = 0;
|
uint8_t _minorVer = 0;
|
||||||
uint8_t _patchVer = 0;
|
uint8_t _patchVer = 0;
|
||||||
|
|
||||||
uint8_t* _digitalInputStates;
|
uint8_t* _digitalInputStates = NULL;
|
||||||
uint8_t* _analogueInputStates;
|
uint8_t* _analogueInputStates = NULL;
|
||||||
uint8_t* _analogueInputBuffer; // buffer for I2C input transfers
|
uint8_t* _analogueInputBuffer = NULL; // buffer for I2C input transfers
|
||||||
uint8_t _readCommandBuffer[1];
|
uint8_t _readCommandBuffer[1];
|
||||||
|
|
||||||
uint8_t _digitalPinBytes = 0; // Size of allocated memory buffer (may be longer than needed)
|
uint8_t _digitalPinBytes = 0; // Size of allocated memory buffer (may be longer than needed)
|
||||||
uint8_t _analoguePinBytes = 0; // Size of allocated memory buffers (may be longer than needed)
|
uint8_t _analoguePinBytes = 0; // Size of allocated memory buffer (may be longer than needed)
|
||||||
uint8_t* _analoguePinMap;
|
uint8_t* _analoguePinMap = NULL;
|
||||||
I2CRB _i2crb;
|
I2CRB _i2crb;
|
||||||
|
|
||||||
enum {RDS_IDLE, RDS_DIGITAL, RDS_ANALOGUE}; // Read operation states
|
enum {RDS_IDLE, RDS_DIGITAL, RDS_ANALOGUE}; // Read operation states
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
# My (FranziHH) DCC++ Ex Hardware
|
||||||
|
<img src="/images/IMG_5870_1.jpg" height="400px" title="DCC++ Ex Hardware">
|
||||||
|
|
||||||
|
|
||||||
# What is DCC++ EX?
|
# What is DCC++ EX?
|
||||||
DCC++ EX is the organization maintaining several codebases that together represent a fully open source DCC system. Currently, this includes the following:
|
DCC++ EX is the organization maintaining several codebases that together represent a fully open source DCC system. Currently, this includes the following:
|
||||||
|
|
||||||
|
|
|
@ -363,11 +363,17 @@ wifiSerialState WifiInterface::setup2(const FSH* SSid, const FSH* password,
|
||||||
}
|
}
|
||||||
ipString[ipLen]=ipChar;
|
ipString[ipLen]=ipChar;
|
||||||
}
|
}
|
||||||
LCD(4,F("%s"),ipString); // There is not enough room on some LCDs to put a title to this
|
#ifndef PRINT_IP_PORT_SINGLE_LINE
|
||||||
|
LCD(4,F("%s"),ipString); // There is not enough room on some LCDs to put a title to this
|
||||||
|
#else
|
||||||
|
LCD(4,F("%s:%d"),ipString,port); // *** Single IP:Port
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
// suck up anything after the IP.
|
// suck up anything after the IP.
|
||||||
if (!checkForOK(1000, true, false)) return WIFI_DISCONNECTED;
|
if (!checkForOK(1000, true, false)) return WIFI_DISCONNECTED;
|
||||||
LCD(5,F("PORT=%d"),port);
|
#ifndef PRINT_IP_PORT_SINGLE_LINE
|
||||||
|
LCD(5,F("PORT=%d"),port);
|
||||||
|
#endif
|
||||||
|
|
||||||
return WIFI_CONNECTED;
|
return WIFI_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,6 +167,9 @@ The configuration file for DCC-EX Command Station
|
||||||
// * #define SCROLLMODE 2 is by row (move up 1 row at a time).
|
// * #define SCROLLMODE 2 is by row (move up 1 row at a time).
|
||||||
#define SCROLLMODE 1
|
#define SCROLLMODE 1
|
||||||
|
|
||||||
|
// Shows IP and Port on Display in a single line
|
||||||
|
// #define PRINT_IP_PORT_SINGLE_LINE
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
// DISABLE EEPROM
|
// DISABLE EEPROM
|
||||||
//
|
//
|
||||||
|
@ -239,7 +242,10 @@ The configuration file for DCC-EX Command Station
|
||||||
// SAMD/SAMC and STM32 have up to 6.)
|
// SAMD/SAMC and STM32 have up to 6.)
|
||||||
// To monitor a throttle on one or more serial ports, uncomment the defines below.
|
// To monitor a throttle on one or more serial ports, uncomment the defines below.
|
||||||
// NOTE: do not define here the WiFi shield serial port or your wifi will not work.
|
// NOTE: do not define here the WiFi shield serial port or your wifi will not work.
|
||||||
//
|
// -------------------------------------
|
||||||
|
// For Use with FastClock serial: uncomment the needed serial Port and
|
||||||
|
// FastClock will work, no further actions are needed
|
||||||
|
// -------------------------------------
|
||||||
//#define SERIAL1_COMMANDS
|
//#define SERIAL1_COMMANDS
|
||||||
//#define SERIAL2_COMMANDS
|
//#define SERIAL2_COMMANDS
|
||||||
//#define SERIAL3_COMMANDS
|
//#define SERIAL3_COMMANDS
|
||||||
|
@ -247,6 +253,17 @@ The configuration file for DCC-EX Command Station
|
||||||
//#define SERIAL5_COMMANDS
|
//#define SERIAL5_COMMANDS
|
||||||
//#define SERIAL6_COMMANDS
|
//#define SERIAL6_COMMANDS
|
||||||
//
|
//
|
||||||
|
// -------------------------------------
|
||||||
|
// FastClock with I2C
|
||||||
|
// uncomment the following Line and Set the used I2C Address
|
||||||
|
//#define FAST_CLOCK_I2C 0x55 // default is 0x55
|
||||||
|
// -------------------------------------
|
||||||
|
//
|
||||||
|
// -------------------------------------
|
||||||
|
// FastClock in HH:MM on Display
|
||||||
|
//#define FASTCLOCK_READABLE
|
||||||
|
// -------------------------------------
|
||||||
|
//
|
||||||
// BLUETOOTH SERIAL ON ESP32
|
// BLUETOOTH SERIAL ON ESP32
|
||||||
// On ESP32 you have the possibility to use the builtin BT serial to connect to
|
// On ESP32 you have the possibility to use the builtin BT serial to connect to
|
||||||
// the CS.
|
// the CS.
|
||||||
|
|
BIN
images/IMG_5870_1.jpg
Normal file
BIN
images/IMG_5870_1.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 741 KiB |
|
@ -3,7 +3,10 @@
|
||||||
|
|
||||||
#include "StringFormatter.h"
|
#include "StringFormatter.h"
|
||||||
|
|
||||||
#define VERSION "5.0.7"
|
#define VERSION "5.0.9"
|
||||||
|
// 5.0.9 - EX-IOExpander bug fix for memory allocation
|
||||||
|
// - EX-IOExpander bug fix to allow for devices with no analogue or no digital pins
|
||||||
|
// 5.0.8 - Bugfix: Do not crash on turnouts without description
|
||||||
// 5.0.7 - Only flag 2.2.0.0-dev as broken, not 2.2.0.0
|
// 5.0.7 - Only flag 2.2.0.0-dev as broken, not 2.2.0.0
|
||||||
// 5.0.6 - Bugfix lost TURNOUTL description
|
// 5.0.6 - Bugfix lost TURNOUTL description
|
||||||
// 5.0.5 - Bugfix version detection logic and better message
|
// 5.0.5 - Bugfix version detection logic and better message
|
||||||
|
|
Loading…
Reference in New Issue
Block a user