Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Giga onboard Wifi, and signal updates. #364

Merged
merged 32 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
dfa798c
seems to work now
travis-farmer Nov 2, 2023
701bc0a
keeping up to date - cleaning
travis-farmer Nov 2, 2023
b1f5c34
compiles, but crashes on client connect
travis-farmer Nov 3, 2023
05db1bd
cleaning
travis-farmer Nov 3, 2023
d95d9c1
allows client, but immidiatly drops client
travis-farmer Nov 3, 2023
b632088
cleaning...
travis-farmer Nov 3, 2023
741771c
added diags for debug tracking...
travis-farmer Nov 3, 2023
050fed6
crashes
travis-farmer Nov 3, 2023
8a813c2
updating current, still crashes
travis-farmer Nov 3, 2023
e6797d1
Giga wifi works for 3 clients MAX
travis-farmer Nov 4, 2023
4430e9a
committing to save, see pull comment
travis-farmer Nov 6, 2023
832ec44
clean up IP reading
travis-farmer Nov 7, 2023
6b731d6
fixed timers, still only two tracks
travis-farmer Nov 7, 2023
8223d30
added XGIGA config for giga experimental
travis-farmer Nov 7, 2023
f254643
added note about SystemCoreClock
travis-farmer Nov 7, 2023
c458e98
digitalPinToPort back from arduino core
travis-farmer Nov 8, 2023
5c0ab9a
pre-test storing of signal updates
travis-farmer Nov 10, 2023
36db724
fixed Typo
travis-farmer Nov 10, 2023
40c0c20
Post tests - PASSED
travis-farmer Nov 10, 2023
904fd5a
possible fix for 4+ tracks
travis-farmer Nov 10, 2023
9a6a305
so far, 8 good signals, one (tested) is DC
travis-farmer Nov 10, 2023
98f0030
removed I2C port change option as it is breaking
travis-farmer Nov 10, 2023
83a22df
12-bit analog, vs just 10-bit
travis-farmer Nov 12, 2023
35d1247
commit current
travis-farmer Nov 14, 2023
9614703
getting rid of a comment
travis-farmer Nov 16, 2023
7f430ce
current
travis-farmer Nov 18, 2023
330bdf5
works, but uses multi connects per client
travis-farmer Nov 18, 2023
1d881a4
cleaning up
travis-farmer Nov 18, 2023
5aca3a6
solved WiFiNINA reset/restart bug
travis-farmer Nov 19, 2023
1a4fff8
adding more locos for Giga
travis-farmer Nov 19, 2023
5906735
patching in PR # 366
travis-farmer Nov 19, 2023
d690b09
parse "@"
travis-farmer Nov 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions CommandDistributor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,50 @@ void CommandDistributor::broadcastRaw(clientType type, char * msg) {
void CommandDistributor::broadcastTrackState(const FSH* format,byte trackLetter, int16_t dcAddr) {
broadcastReply(COMMAND_TYPE, format,trackLetter, dcAddr);
}

Print * CommandDistributor::getVirtualLCDSerial(byte screen, byte row) {
Print * stream=virtualLCDSerial;
#ifdef CD_HANDLE_RING
rememberVLCDClient=RingStream::NO_CLIENT;
if (!stream && virtualLCDClient!=RingStream::NO_CLIENT) {
// 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.
if ((rememberVLCDClient = ring->peekTargetMark()) != RingStream::NO_CLIENT) {
ring->commit();
}
ring->mark(virtualLCDClient);
stream=ring;
}
#endif
if (stream) StringFormatter::send(stream,F("<@ %d %d \""), screen,row);
return stream;
}

void CommandDistributor::commitVirtualLCDSerial() {
#ifdef CD_HANDLE_RING
if (virtualLCDClient!=RingStream::NO_CLIENT) {
StringFormatter::send(ring,F("\">\n"));
ring->commit();
if (rememberVLCDClient!=RingStream::NO_CLIENT) ring->mark(rememberVLCDClient);
return;
}
#endif
StringFormatter::send(virtualLCDSerial,F("\">\n"));
}

void CommandDistributor::setVirtualLCDSerial(Print * stream) {
#ifdef CD_HANDLE_RING
virtualLCDClient=RingStream::NO_CLIENT;
if (stream && stream->availableForWrite()==RingStream::THIS_IS_A_RINGSTREAM) {
virtualLCDClient=((RingStream *) stream)->peekTargetMark();
virtualLCDSerial=nullptr;
return;
}
#endif
virtualLCDSerial=stream;
}

Print* CommandDistributor::virtualLCDSerial=nullptr;
byte CommandDistributor::virtualLCDClient=0xFF;
byte CommandDistributor::rememberVLCDClient=0;
8 changes: 8 additions & 0 deletions CommandDistributor.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ public :
template<typename... Targs> static void broadcastReply(clientType type, Targs... msg);
static void forget(byte clientId);

// Handling code for virtual LCD receiver.
static Print * getVirtualLCDSerial(byte screen, byte row);
static void commitVirtualLCDSerial();
static void setVirtualLCDSerial(Print * stream);
private:
static Print * virtualLCDSerial;
static byte virtualLCDClient;
static byte rememberVLCDClient;
};

#endif
4 changes: 4 additions & 0 deletions DCC.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ const uint16_t LONG_ADDR_MARKER = 0x4000;
// Allocations with memory implications..!
// Base system takes approx 900 bytes + 8 per loco. Turnouts, Sensors etc are dynamically created
#if defined(HAS_ENOUGH_MEMORY)
#if defined(ARDUINO_GIGA) // yes giga
const byte MAX_LOCOS = 100;
#else // no giga
const byte MAX_LOCOS = 50;
#endif // giga
#else
const byte MAX_LOCOS = 30;
#endif
Expand Down
7 changes: 7 additions & 0 deletions DCCEXParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,13 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
case 'L': // LCC interface implemented in EXRAIL parser
break; // Will <X> if not intercepted by EXRAIL

case '@': // JMRI saying "give me virtual LCD msgs"
CommandDistributor::setVirtualLCDSerial(stream);
StringFormatter::send(stream,
F("<@ 0 0 \"DCC-EX v" VERSION "\">\n"
"<@ 0 1 \"Lic GPLv3\">\n"));
return;

default: //anything else will diagnose and drop out to <X>
DIAG(F("Opcode=%c params=%d"), opcode, params);
for (int i = 0; i < params; i++)
Expand Down
1 change: 1 addition & 0 deletions DCCTimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class DCCTimer {
#if defined(ARDUINO_ARCH_STM32) // TODO: PMA temporary hack - assumes 100Mhz F_CPU as STM32 can change frequency
static const long CLOCK_CYCLES=(100000000L / 1000000 * DCC_SIGNAL_TIME) >>1;
#elif defined(ARDUINO_GIGA)
///TJF: we could get F_CPU from SystemCoreClock, but it will not allow as it is a non-constant value
static const long CLOCK_CYCLES=(480000000L / 1000000 * DCC_SIGNAL_TIME) >>1;
#else
static const long CLOCK_CYCLES=(F_CPU / 1000000 * DCC_SIGNAL_TIME) >>1;
Expand Down
111 changes: 49 additions & 62 deletions DCCTimerGiga.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,19 @@

INTERRUPT_CALLBACK interruptHandler=0;

//HardwareTimer* timer = NULL;
//HardwareTimer* timerAux = NULL;
HardwareTimer timer(TIM2);
HardwareTimer timerAux(TIM3);

static bool tim2ModeHA = false;
static bool tim3ModeHA = false;
#ifndef DCC_EX_TIMER
#if defined(TIM6)
#define DCC_EX_TIMER TIM6
#elif defined(TIM7)
#define DCC_EX_TIMER TIM7
#elif defined(TIM12)
#define DCC_EX_TIMER TIM12
#else
#warning This Giga variant does not have Timers 1,8 or 11!!
#endif
#endif // ifndef DCC_EX_TIMER

HardwareTimer dcctimer(TIM8);
void DCCTimer_Handler() __attribute__((interrupt));

void DCCTimer_Handler() {
Expand All @@ -59,66 +64,38 @@ void DCCTimer_Handler() {

void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
interruptHandler=callback;
noInterrupts();

// adc_set_sample_rate(ADC_SAMPLETIME_480CYCLES);
timer.pause();
timerAux.pause();
timer.setPrescaleFactor(1);
timer.setOverflow(DCC_SIGNAL_TIME, MICROSEC_FORMAT);
timer.attachInterrupt(DCCTimer_Handler);
timer.refresh();
timerAux.setPrescaleFactor(1);
timerAux.setOverflow(DCC_SIGNAL_TIME, MICROSEC_FORMAT);
timerAux.refresh();

timer.resume();
timerAux.resume();

interrupts();
noInterrupts();

dcctimer.pause();
dcctimer.setPrescaleFactor(1);
// timer.setOverflow(CLOCK_CYCLES * 2);
dcctimer.setOverflow(DCC_SIGNAL_TIME, MICROSEC_FORMAT);
// dcctimer.attachInterrupt(Timer11_Handler);
dcctimer.attachInterrupt(DCCTimer_Handler);
dcctimer.setInterruptPriority(0, 0); // Set highest preemptive priority!
dcctimer.refresh();
dcctimer.resume();

interrupts();
}

bool DCCTimer::isPWMPin(byte pin) {
switch (pin) {
case 12:
return true;
case 13:
return true;
default:
return false;
}
//TODO: STM32 whilst this call to digitalPinHasPWM will reveal which pins can do PWM,
// there's no support yet for High Accuracy, so for now return false
// return digitalPinHasPWM(pin);
(void) pin;
return false;
}

void DCCTimer::setPWM(byte pin, bool high) {
switch (pin) {
case 12:
if (!tim3ModeHA) {
timerAux.setMode(1, TIMER_OUTPUT_COMPARE_INACTIVE, 12);
tim3ModeHA = true;
}
if (high)
TIM2->CCMR1 = (TIM2->CCMR1 & ~TIM_CCMR1_OC1M_Msk) | TIM_CCMR1_OC1M_0;
else
TIM2->CCMR1 = (TIM2->CCMR1 & ~TIM_CCMR1_OC1M_Msk) | TIM_CCMR1_OC1M_1;
break;
case 13:
if (!tim2ModeHA) {
timer.setMode(1, TIMER_OUTPUT_COMPARE_INACTIVE, 13);
tim2ModeHA = true;
}
if (high)
TIM3->CCMR1 = (TIM3->CCMR1 & ~TIM_CCMR1_OC1M_Msk) | TIM_CCMR1_OC1M_0;
else
TIM3->CCMR1 = (TIM3->CCMR1 & ~TIM_CCMR1_OC1M_Msk) | TIM_CCMR1_OC1M_1;
break;
}
// TODO: High Accuracy mode is not supported as yet, and may never need to be
(void) pin;
(void) high;
return;
}

void DCCTimer::clearPWM() {
timer.setMode(1, TIMER_OUTPUT_COMPARE_INACTIVE, NC);
tim2ModeHA = false;
timerAux.setMode(1, TIMER_OUTPUT_COMPARE_INACTIVE, NC);
tim3ModeHA = false;
return;
}

void DCCTimer::getSimulatedMacAddress(byte mac[6]) {
Expand Down Expand Up @@ -161,32 +138,42 @@ void DCCTimer::reset() {
//Watchdog::start(500);

//while(true) {};
return;
}

int * ADCee::analogvals = NULL;

int16_t ADCee::ADCmax()
{
return 1023;
return 4095;
}

AdvancedADC adc(A0, A1);
AdvancedADC adc;
pin_size_t active_pins[] = {A0, A1, A2, A3};
pin_size_t active_pinsB[] = {A4, A5, A6, A7};
int num_active_pins = 4;
const int samples_per_round = 512;
int ADCee::init(uint8_t pin) {
adc.begin(AN_RESOLUTION_10, 16000, 1, 512);
adc.stop();
if (pin >= A0 && pin <= A3) adc.begin(AN_RESOLUTION_12, 16000, 1, samples_per_round, num_active_pins, active_pins);
else if (pin >= A4 && pin <= A7) adc.begin(AN_RESOLUTION_12, 16000, 1, samples_per_round, num_active_pins, active_pinsB);
return 123;
}

/*
* Read function ADCee::read(pin) to get value instead of analogRead(pin)
*/
int ADCee::read(uint8_t pin, bool fromISR) {
int tmpPin = 0;
if (pin >= A0 && pin <= A3) tmpPin = (pin - A0);
else if (pin >= A4 && pin <= A7) tmpPin = ((pin - A0) - 4);
static SampleBuffer buf = adc.read();
int retVal = -123;
if (adc.available()) {
buf.release();
buf = adc.read();
}
return (buf[pin - A0]);
return (buf[tmpPin]);
}

/*
Expand Down
48 changes: 22 additions & 26 deletions I2CManager_Wire.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,17 @@
#define WIRE_HAS_TIMEOUT
#endif

#if defined(GIGA_I2C_1)
#define DCCEX_WIRE Wire1
#else
#define DCCEX_WIRE Wire
#endif




/***************************************************************************
* Initialise I2C interface software
***************************************************************************/
void I2CManagerClass::_initialise() {
DCCEX_WIRE.begin();
Wire.begin();
#if defined(WIRE_HAS_TIMEOUT)
DCCEX_WIRE.setWireTimeout(_timeout, true);
Wire.setWireTimeout(_timeout, true);
#endif
}

Expand All @@ -58,7 +54,7 @@ void I2CManagerClass::_initialise() {
* on Arduino. Mega4809 supports 1000000 (Fast+) too.
***************************************************************************/
void I2CManagerClass::_setClock(unsigned long i2cClockSpeed) {
DCCEX_WIRE.setClock(i2cClockSpeed);
Wire.setClock(i2cClockSpeed);
}

/***************************************************************************
Expand All @@ -69,7 +65,7 @@ void I2CManagerClass::_setClock(unsigned long i2cClockSpeed) {
void I2CManagerClass::setTimeout(unsigned long value) {
_timeout = value;
#if defined(WIRE_HAS_TIMEOUT)
DCCEX_WIRE.setWireTimeout(value, true);
Wire.setWireTimeout(value, true);
#endif
}

Expand All @@ -82,7 +78,7 @@ static uint8_t muxSelect(I2CAddress address) {
I2CMux muxNo = address.muxNumber();
I2CSubBus subBus = address.subBus();
if (muxNo != I2CMux_None) {
DCCEX_WIRE.beginTransmission(I2C_MUX_BASE_ADDRESS+muxNo);
Wire.beginTransmission(I2C_MUX_BASE_ADDRESS+muxNo);
uint8_t data = (subBus == SubBus_All) ? 0xff :
(subBus == SubBus_None) ? 0x00 :
#if defined(I2CMUX_PCA9547)
Expand All @@ -94,8 +90,8 @@ static uint8_t muxSelect(I2CAddress address) {
// with a bit set for the subBus to be enabled
1 << subBus;
#endif
DCCEX_WIRE.write(&data, 1);
return DCCEX_WIRE.endTransmission(true); // have to release I2C bus for it to work
Wire.write(&data, 1);
return Wire.endTransmission(true); // have to release I2C bus for it to work
}
return I2C_STATUS_OK;
}
Expand All @@ -118,9 +114,9 @@ uint8_t I2CManagerClass::write(I2CAddress address, const uint8_t buffer[], uint8
#endif
// Only send new transaction if address is non-zero.
if (muxStatus == I2C_STATUS_OK && address != 0) {
DCCEX_WIRE.beginTransmission(address);
if (size > 0) DCCEX_WIRE.write(buffer, size);
status = DCCEX_WIRE.endTransmission();
Wire.beginTransmission(address);
if (size > 0) Wire.write(buffer, size);
status = Wire.endTransmission();
}
#ifdef I2C_EXTENDED_ADDRESS
// Deselect MUX if there's more than one MUX present, to avoid having multiple ones selected
Expand Down Expand Up @@ -169,25 +165,25 @@ uint8_t I2CManagerClass::read(I2CAddress address, uint8_t readBuffer[], uint8_t
// Only start new transaction if address is non-zero.
if (muxStatus == I2C_STATUS_OK && address != 0) {
if (writeSize > 0) {
DCCEX_WIRE.beginTransmission(address);
DCCEX_WIRE.write(writeBuffer, writeSize);
status = DCCEX_WIRE.endTransmission(false); // Don't free bus yet
Wire.beginTransmission(address);
Wire.write(writeBuffer, writeSize);
status = Wire.endTransmission(false); // Don't free bus yet
}
if (status == I2C_STATUS_OK) {
#ifdef WIRE_HAS_TIMEOUT
DCCEX_WIRE.clearWireTimeoutFlag();
DCCEX_WIRE.requestFrom(address, (size_t)readSize);
if (!DCCEX_WIRE.getWireTimeoutFlag()) {
while (DCCEX_WIRE.available() && nBytes < readSize)
readBuffer[nBytes++] = DCCEX_WIRE.read();
Wire.clearWireTimeoutFlag();
Wire.requestFrom(address, (size_t)readSize);
if (!Wire.getWireTimeoutFlag()) {
while (Wire.available() && nBytes < readSize)
readBuffer[nBytes++] = Wire.read();
if (nBytes < readSize) status = I2C_STATUS_TRUNCATED;
} else {
status = I2C_STATUS_TIMEOUT;
}
#else
DCCEX_WIRE.requestFrom(address, (size_t)readSize);
while (DCCEX_WIRE.available() && nBytes < readSize)
readBuffer[nBytes++] = DCCEX_WIRE.read();
Wire.requestFrom(address, (size_t)readSize);
while (Wire.available() && nBytes < readSize)
readBuffer[nBytes++] = Wire.read();
if (nBytes < readSize) status = I2C_STATUS_TRUNCATED;
#endif
}
Expand Down
Loading