From 06c0091f406c40dd10bb5268d13816074bd31f16 Mon Sep 17 00:00:00 2001 From: Peter Muth Date: Thu, 30 Dec 2021 17:04:42 +0100 Subject: [PATCH 1/8] Read startbit to make sure we were not started by a glitch --- utility/ln_sw_uart.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/utility/ln_sw_uart.cpp b/utility/ln_sw_uart.cpp index f41a90d..fc26581 100755 --- a/utility/ln_sw_uart.cpp +++ b/utility/ln_sw_uart.cpp @@ -192,6 +192,9 @@ ISR(LN_SB_SIGNAL) // Reset the bit counter so that on first increment it is on 0 lnBitCount = 0; + // Next bit is startbit + checkStartBit=true; + #if defined(ESP8266) // Must clear this bit in the interrupt register, // it gets set even when interrupts are disabled @@ -228,6 +231,29 @@ ISR(LN_TMR_SIGNAL) /* signal handler for timer0 overflow */ LN_TMR_OUTP_CAPT_REG = lnCompareTarget; # endif #endif + + // Check if there is really a start bit or just a glitch + if (checkStartBit) { + checkStartBit = false; + if (bit_is_set(LN_RX_PORT, LN_RX_BIT)) { + lnState = LN_ST_CD_BACKOFF; +#if defined(ESP8266) + // Enable the pin interrupt +#ifdef LN_SW_UART_RX_INVERTED + attachInterrupt(digitalPinToInterrupt(LN_RX_PORT), ln_esp8266_pin_isr, RISING); +#else + attachInterrupt(digitalPinToInterrupt(LN_RX_PORT), ln_esp8266_pin_isr, FALLING); +#endif +#else + // Clear the Start Bit Interrupt Status Flag and Enable ready to + // detect the next Start Bit + LN_CLEAR_START_BIT_FLAG(); + LN_ENABLE_START_BIT_INTERRUPT(); +#endif + } + return; + } + lnBitCount++; // Increment bit_counter if (lnState == LN_ST_RX) { // Are we in RX mode From ebe89fffc38052a8f07d42dd3a512dd2e3cd732f Mon Sep 17 00:00:00 2001 From: Peter Muth Date: Thu, 30 Dec 2021 17:21:02 +0100 Subject: [PATCH 2/8] Read startbit to make sure we were not started by a glitch --- utility/ln_sw_uart.cpp | 13 ++++++++----- utility/ln_sw_uart.h | 3 ++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/utility/ln_sw_uart.cpp b/utility/ln_sw_uart.cpp index fc26581..b72e0c0 100755 --- a/utility/ln_sw_uart.cpp +++ b/utility/ln_sw_uart.cpp @@ -73,6 +73,8 @@ volatile uint8_t lnBitCount; volatile uint8_t lnCurrentByte; volatile LnCompareTargetType lnCompareTarget; +bool checkStartBit = false; + LnBuf* lnRxBuffer; volatile lnMsg* volatile lnTxData; volatile uint8_t lnTxIndex; @@ -191,10 +193,11 @@ ISR(LN_SB_SIGNAL) // Reset the bit counter so that on first increment it is on 0 lnBitCount = 0; - - // Next bit is startbit + + // Next Bit ist Startbit checkStartBit=true; + #if defined(ESP8266) // Must clear this bit in the interrupt register, // it gets set even when interrupts are disabled @@ -239,13 +242,13 @@ ISR(LN_TMR_SIGNAL) /* signal handler for timer0 overflow */ lnState = LN_ST_CD_BACKOFF; #if defined(ESP8266) // Enable the pin interrupt -#ifdef LN_SW_UART_RX_INVERTED +#ifdef LN_SW_UART_RX_INVERTED attachInterrupt(digitalPinToInterrupt(LN_RX_PORT), ln_esp8266_pin_isr, RISING); #else attachInterrupt(digitalPinToInterrupt(LN_RX_PORT), ln_esp8266_pin_isr, FALLING); #endif #else - // Clear the Start Bit Interrupt Status Flag and Enable ready to + // Clear the Start Bit Interrupt Status Flag and Enable ready to // detect the next Start Bit LN_CLEAR_START_BIT_FLAG(); LN_ENABLE_START_BIT_INTERRUPT(); @@ -253,7 +256,7 @@ ISR(LN_TMR_SIGNAL) /* signal handler for timer0 overflow */ } return; } - + lnBitCount++; // Increment bit_counter if (lnState == LN_ST_RX) { // Are we in RX mode diff --git a/utility/ln_sw_uart.h b/utility/ln_sw_uart.h index a07d8ea..abe0f2f 100755 --- a/utility/ln_sw_uart.h +++ b/utility/ln_sw_uart.h @@ -152,7 +152,8 @@ // The Start Bit period is a full bit period + half of the next bit period // so that the bit is sampled in middle of the bit -#define LN_TIMER_RX_START_PERIOD LN_BIT_PERIOD + (LN_BIT_PERIOD / 2) +//#define LN_TIMER_RX_START_PERIOD LN_BIT_PERIOD + (LN_BIT_PERIOD / 2) +#define LN_TIMER_RX_START_PERIOD LN_BIT_PERIOD / 2 // Read Startbit to make sure we are not started by a glitch #define LN_TIMER_RX_RELOAD_PERIOD LN_BIT_PERIOD #define LN_TIMER_TX_RELOAD_PERIOD LN_BIT_PERIOD From bc12662b7c711864a902740a307775093d2c6986 Mon Sep 17 00:00:00 2001 From: Peter Muth Date: Thu, 30 Dec 2021 18:06:02 +0100 Subject: [PATCH 3/8] Make the glitch detection work also in case we define LN_SW_UART_RX_INVERTED --- utility/ln_sw_uart.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/utility/ln_sw_uart.cpp b/utility/ln_sw_uart.cpp index b72e0c0..4f217f3 100755 --- a/utility/ln_sw_uart.cpp +++ b/utility/ln_sw_uart.cpp @@ -238,7 +238,11 @@ ISR(LN_TMR_SIGNAL) /* signal handler for timer0 overflow */ // Check if there is really a start bit or just a glitch if (checkStartBit) { checkStartBit = false; +#ifdef LN_SW_UART_RX_INVERTED + if (bit_is_clear(LN_RX_PORT, LN_RX_BIT)) { +#else if (bit_is_set(LN_RX_PORT, LN_RX_BIT)) { +#endif lnState = LN_ST_CD_BACKOFF; #if defined(ESP8266) // Enable the pin interrupt From aeae55d38d42aeabd9d648a8e426efc6f35df3a7 Mon Sep 17 00:00:00 2001 From: Philipp Gahtow Date: Wed, 12 Jan 2022 09:27:19 +0100 Subject: [PATCH 4/8] Update ln_config.h fix to work correct on ESP8266 with other Loconet peripherals. --- utility/ln_config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utility/ln_config.h b/utility/ln_config.h index 07e962d..993ec24 100755 --- a/utility/ln_config.h +++ b/utility/ln_config.h @@ -92,7 +92,7 @@ typedef volatile LnPortRegisterType* LnPortAddrType; #define LN_SW_UART_TX_INVERTED #ifdef ESP8266 -# define LN_BIT_PERIOD ((F_CPU / 16) / 16666) +# define LN_BIT_PERIOD 4720 //((F_CPU / 16) / 16666) //PG: 11.01.2022 correct ESP speed --> CPU Frequenz != Timer Frequenz!!! # define LN_TIMER_TX_RELOAD_ADJUST 60 #else # if defined(STM32F1) @@ -241,4 +241,4 @@ typedef volatile LnPortRegisterType* LnPortAddrType; #endif // board type -#endif // include file \ No newline at end of file +#endif // include file From dc237f7032fd08a914e9aa8b479e270a8fc4b79d Mon Sep 17 00:00:00 2001 From: Philipp Gahtow Date: Wed, 12 Jan 2022 09:35:32 +0100 Subject: [PATCH 5/8] update version after ESP8266 timing fix --- library.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index a396707..5b2385f 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=LocoNet -version=1.1.8 +version=1.1.9 author=Alex Shepherd, John Plocher, Damian Philipp, Tom Knox, Hans Tanner, Björn Rennfanz maintainer=Alex Shepherd sentence=Enables Digitrax LocoNet Communication paragraph=This library allows you to interface to a LocoNet network and send/receive LocoNet commands. The library currently supports the AVR ATTiny84 & ATMega88/168/328/32u4 using the 16-Bit Timer1 and ICP1. It also supports the Mega2560 using Timer5 and ICP5. It also supports the STM32F1 using TIM2 and the ESP8266 uses an hardware interrupt driven software uart. category=Communication url=http://mrrwa.org/loconet-interface/ -architectures=avr,esp8266,stm32 \ No newline at end of file +architectures=avr,esp8266,stm32 From 820a266c7de58e0b18057c8371db0c2a7e7bf5f2 Mon Sep 17 00:00:00 2001 From: Philipp Gahtow Date: Wed, 12 Jan 2022 09:36:57 +0100 Subject: [PATCH 6/8] fix to work correct on ESP8266 with other Loconet peripherals --- utility/ln_sw_uart.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utility/ln_sw_uart.cpp b/utility/ln_sw_uart.cpp index 4f217f3..920830f 100755 --- a/utility/ln_sw_uart.cpp +++ b/utility/ln_sw_uart.cpp @@ -436,7 +436,7 @@ void initLocoNetHardware(LnBuf * RxBuffer) #if defined(ESP8266) timer1_detachInterrupt(); - timer1_enable(TIM_DIV16, TIM_EDGE, TIM_SINGLE); + timer1_enable(TIM_DIV1, TIM_EDGE, TIM_SINGLE); //remove divider to make timing more accurate #elif defined(STM32F1) // === Setup the timer === From cca021d638319be2945eca94a1430af53cad8cd1 Mon Sep 17 00:00:00 2001 From: Alex Shepherd Date: Mon, 7 Feb 2022 14:24:24 +1300 Subject: [PATCH 7/8] added missing notify functions --- examples/LocoNetMonitor/LocoNetMonitor.ino | 239 ++++++++++++--------- 1 file changed, 141 insertions(+), 98 deletions(-) diff --git a/examples/LocoNetMonitor/LocoNetMonitor.ino b/examples/LocoNetMonitor/LocoNetMonitor.ino index 839c0ec..9df8e66 100644 --- a/examples/LocoNetMonitor/LocoNetMonitor.ino +++ b/examples/LocoNetMonitor/LocoNetMonitor.ino @@ -1,98 +1,141 @@ -#include - -// LocoNet Packet Monitor -// Demonstrates the use of the: -// -// LocoNet.processSwitchSensorMessage(LnPacket) -// -// function and examples of each of the notifyXXXXXXX user call-back functions - -lnMsg *LnPacket; - -void setup() { - // First initialize the LocoNet interface - LocoNet.init(); - - // Configure the serial port for 57600 baud - Serial.begin(57600); - Serial.println("LocoNet Monitor"); -} - -void loop() { - // Check for any received LocoNet packets - LnPacket = LocoNet.receive() ; - if ( LnPacket ) { - // First print out the packet in HEX - Serial.print("RX: "); - uint8_t msgLen = getLnMsgSize(LnPacket); - for (uint8_t x = 0; x < msgLen; x++) - { - uint8_t val = LnPacket->data[x]; - // Print a leading 0 if less than 16 to make 2 HEX digits - if (val < 16) - Serial.print('0'); - - Serial.print(val, HEX); - Serial.print(' '); - } - - // If this packet was not a Switch or Sensor Message then print a new line - if (!LocoNet.processSwitchSensorMessage(LnPacket)) { - Serial.println(); - } - } -} - -// This call-back function is called from LocoNet.processSwitchSensorMessage -// for all Sensor messages -void notifySensor( uint16_t Address, uint8_t State ) { - Serial.print("Sensor: "); - Serial.print(Address, DEC); - Serial.print(" - "); - Serial.println( State ? "Active" : "Inactive" ); -} - -// This call-back function is called from LocoNet.processSwitchSensorMessage -// for all Switch Request messages -void notifySwitchRequest( uint16_t Address, uint8_t Output, uint8_t Direction ) { - Serial.print("Switch Request: "); - Serial.print(Address, DEC); - Serial.print(':'); - Serial.print(Direction ? "Closed" : "Thrown"); - Serial.print(" - "); - Serial.println(Output ? "On" : "Off"); -} - -// This call-back function is called from LocoNet.processSwitchSensorMessage -// for all Switch Output Report messages -void notifySwitchOutputsReport( uint16_t Address, uint8_t ClosedOutput, uint8_t ThrownOutput) { - Serial.print("Switch Outputs Report: "); - Serial.print(Address, DEC); - Serial.print(": Closed - "); - Serial.print(ClosedOutput ? "On" : "Off"); - Serial.print(": Thrown - "); - Serial.println(ThrownOutput ? "On" : "Off"); -} - -// This call-back function is called from LocoNet.processSwitchSensorMessage -// for all Switch Sensor Report messages -void notifySwitchReport( uint16_t Address, uint8_t State, uint8_t Sensor ) { - Serial.print("Switch Sensor Report: "); - Serial.print(Address, DEC); - Serial.print(':'); - Serial.print(Sensor ? "Switch" : "Aux"); - Serial.print(" - "); - Serial.println( State ? "Active" : "Inactive" ); -} - -// This call-back function is called from LocoNet.processSwitchSensorMessage -// for all Switch State messages -void notifySwitchState( uint16_t Address, uint8_t Output, uint8_t Direction ) { - Serial.print("Switch State: "); - Serial.print(Address, DEC); - Serial.print(':'); - Serial.print(Direction ? "Closed" : "Thrown"); - Serial.print(" - "); - Serial.println(Output ? "On" : "Off"); -} - +#include + +// LocoNet Packet Monitor +// Demonstrates the use of the: +// +// LocoNet.processSwitchSensorMessage(LnPacket) +// +// function and examples of each of the notifyXXXXXXX user call-back functions + +lnMsg *LnPacket; + +void setup() { + // First initialize the LocoNet interface + LocoNet.init(); + + // Configure the serial port for 57600 baud + Serial.begin(57600); + Serial.println("LocoNet Monitor"); +} + +void loop() { + // Check for any received LocoNet packets + LnPacket = LocoNet.receive() ; + if ( LnPacket ) { + // First print out the packet in HEX + Serial.print("RX: "); + uint8_t msgLen = getLnMsgSize(LnPacket); + for (uint8_t x = 0; x < msgLen; x++) + { + uint8_t val = LnPacket->data[x]; + // Print a leading 0 if less than 16 to make 2 HEX digits + if (val < 16) + Serial.print('0'); + + Serial.print(val, HEX); + Serial.print(' '); + } + + // If this packet was not a Switch or Sensor Message then print a new line + if (!LocoNet.processSwitchSensorMessage(LnPacket)) { + Serial.println(); + } + } +} + +// This call-back function is called from LocoNet.processSwitchSensorMessage +// for all Sensor messages +void notifySensor( uint16_t Address, uint8_t State ) { + Serial.print("Sensor: "); + Serial.print(Address, DEC); + Serial.print(" - "); + Serial.println( State ? "Active" : "Inactive" ); +} + +// This call-back function is called from LocoNet.processSwitchSensorMessage +// for all Switch Request messages +void notifySwitchRequest( uint16_t Address, uint8_t Output, uint8_t Direction ) { + Serial.print("Switch Request: "); + Serial.print(Address, DEC); + Serial.print(':'); + Serial.print(Direction ? "Closed" : "Thrown"); + Serial.print(" - "); + Serial.println(Output ? "On" : "Off"); +} + +// This call-back function is called from LocoNet.processSwitchSensorMessage +// for all Switch Output Report messages +void notifySwitchOutputsReport( uint16_t Address, uint8_t ClosedOutput, uint8_t ThrownOutput) { + Serial.print("Switch Outputs Report: "); + Serial.print(Address, DEC); + Serial.print(": Closed - "); + Serial.print(ClosedOutput ? "On" : "Off"); + Serial.print(": Thrown - "); + Serial.println(ThrownOutput ? "On" : "Off"); +} + +// This call-back function is called from LocoNet.processSwitchSensorMessage +// for all Switch Sensor Report messages +void notifySwitchReport( uint16_t Address, uint8_t State, uint8_t Sensor ) { + Serial.print("Switch Sensor Report: "); + Serial.print(Address, DEC); + Serial.print(':'); + Serial.print(Sensor ? "Switch" : "Aux"); + Serial.print(" - "); + Serial.println( State ? "Active" : "Inactive" ); +} + +// This call-back function is called from LocoNet.processSwitchSensorMessage +// for all Switch State messages +void notifySwitchState( uint16_t Address, uint8_t Output, uint8_t Direction ) { + Serial.print("Switch State: "); + Serial.print(Address, DEC); + Serial.print(':'); + Serial.print(Direction ? "Closed" : "Thrown"); + Serial.print(" - "); + Serial.println(Output ? "On" : "Off"); +} + +// This call-back function is called from LocoNet.processSwitchSensorMessage +// for all Power messages +void notifyPower(uint8_t State) { + Serial.print("Layout Power State: "); + Serial.println(State ? "On" : "Off"); +} + +// This call-back function is called from LocoNet.processSwitchSensorMessage +// for all MultiSensePower messages +void notifyMultiSensePower(uint8_t BoardID, uint8_t Subdistrict, uint8_t Mode, uint8_t Direction) { + Serial.print("MultiSensePower: Board ID: "); + Serial.print(BoardID, DEC); + Serial.print(" Sub District: "); + Serial.print(Subdistrict, DEC); + Serial.print(" Mode: "); + Serial.print(Mode, DEC); + Serial.print(" Direction: "); + Serial.println(Direction, DEC); +} + +// This call-back function is called from LocoNet.processSwitchSensorMessage +// for all notifyMultiSenseTransponder messages +void notifyMultiSenseTransponder(uint16_t Address, uint8_t Zone, uint16_t LocoAddress, uint8_t Present) { + Serial.print("MultiSenseTransponder: Address: "); + Serial.print(Address, DEC); + Serial.print(" Zone: "); + Serial.print(Zone, DEC); + Serial.print(" Loco Address: "); + Serial.print(LocoAddress, DEC); + Serial.print(" Present: "); + Serial.println(Present, DEC); +} + +// This call-back function is called from LocoNet.processSwitchSensorMessage +// for all LongAck messages + +void notifyLongAck(uint8_t d1, uint8_t d2) { + Serial.print("LongACK : Data Byte 1: "); + Serial.print(d1, DEC); + Serial.print(" Data Byte 2: "); + Serial.println(d2, DEC); + +} From 7223caf5d45cef3794206688f08c903091e418ee Mon Sep 17 00:00:00 2001 From: Alex Shepherd Date: Mon, 7 Feb 2022 14:27:38 +1300 Subject: [PATCH 8/8] Added another example of the LocoNetControlPanel that works using a Serial Terminal instead of buttons and LEDs --- ...conetLayoutControlPanel_SerialTerminal.ino | 199 ++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 examples/LoconetLayoutControlPanel_SerialTerminal/LoconetLayoutControlPanel_SerialTerminal.ino diff --git a/examples/LoconetLayoutControlPanel_SerialTerminal/LoconetLayoutControlPanel_SerialTerminal.ino b/examples/LoconetLayoutControlPanel_SerialTerminal/LoconetLayoutControlPanel_SerialTerminal.ino new file mode 100644 index 0000000..fd26d19 --- /dev/null +++ b/examples/LoconetLayoutControlPanel_SerialTerminal/LoconetLayoutControlPanel_SerialTerminal.ino @@ -0,0 +1,199 @@ + +/* + LocoNet Arduino Layout Controler using Serial Terminal + LocoNetLayoutControlPanel_SerialTerminal.ino + + A standalone controller which will generate LocoNet commands from a computer when key 'o', 'f', 'c' or 'e' is pressed + Turn on track power with 'o' key + Turn off track power with 'f' key + Clear all decoder slots with 'c' key + Stop all engines with 's' key + + RX and TX Loconet + Hardcoded to use ICP pin 8 (port PINB bit PB0) for LocoNet input and a user define'd pin for output/transmit + + Copyright (c) 2012, 2014 John Plocher, released under the terms of the MIT License (MIT) + + Modified by Alex Shephard at Al Silverstein request + + Change from eStop command to Loco Speed command by ALS on 11/9/21 + +*/ + +#include + + +#define LNtxPort 7 // LocoNet Transmit pin (LocoShield uses pin7) + +int MaxSlot = 120; + +typedef enum +{ + CMD_DONE, + CMD_SPEED_ZERO, + CMD_SLOT_CLEAR +} CMD_STATE; + +CMD_STATE CommandState = CMD_DONE; + +String ValidCommands = "ofcis"; + +void sendOPC_GP(byte on) { + lnMsg SendPacket; + if (on) { + SendPacket.data[ 0 ] = OPC_GPON; + } else { + SendPacket.data[ 0 ] = OPC_GPOFF; + } + LocoNet.send( &SendPacket ) ; +} + + +void sendOPC_IDLE() { + lnMsg SendPacket; + SendPacket.data[ 0 ] = OPC_IDLE; + LocoNet.send( &SendPacket ) ; +} + +void send3bytePacket(int opcode, int slot, int spd) { + lnMsg SendPacket; + SendPacket.data[ 0 ] = opcode; + SendPacket.data[ 1 ] = slot; + SendPacket.data[ 2 ] = spd; + LocoNet.send( &SendPacket ); +} +void sendOPC_LOCO_SPD(int slot, int spd) { + send3bytePacket(OPC_LOCO_SPD, slot, spd); +} + +void sendOPC_LOCO_DIRF(int slot, int dirf) { + send3bytePacket(OPC_LOCO_DIRF, slot, dirf); +} + +void sendOPC_LOCO_SND(int slot, int snd) { + send3bytePacket(OPC_LOCO_SND, slot, snd); +} + +void sendOPC_SLOT_STAT1(int slot, int stat) { + send3bytePacket(OPC_SLOT_STAT1, slot, stat); +} + +void sendOPC_RQ_SL_DATA(int slot) { + send3bytePacket(OPC_RQ_SL_DATA, slot, 0); +} + +void processIncomingLoconetCommand(lnMsg* LnPacket) { + if ( LnPacket ) + { + switch(LnPacket->sz.command) + { + case OPC_GPON: + Serial.println("Power ON"); + break; + + case OPC_GPOFF: + Serial.println("Power OFF"); + break; + + case OPC_IDLE: + Serial.println("EStop!"); + break; + + case OPC_SL_RD_DATA: + if (CommandState == CMD_SLOT_CLEAR) + { + if(LnPacket->sd.stat & LOCO_IN_USE) + { + Serial.print("Clear Slot: "); Serial.print(LnPacket->sd.slot); Serial.print(" Status: "); Serial.println(LnPacket->sd.stat, HEX); + LnPacket->sd.command = OPC_WR_SL_DATA; + LnPacket->sd.stat = 0; + LnPacket->sd.adr = 0; + LnPacket->sd.spd = 0; + LnPacket->sd.dirf = 0; + LnPacket->sd.ss2 = 0; + LnPacket->sd.adr2 = 0; + LnPacket->sd.snd = 0; + LnPacket->sd.id1 = 0; + LnPacket->sd.id2 = 0; + LocoNet.send(LnPacket); + } + } + + else if(CommandState == CMD_SPEED_ZERO) + { + if((LnPacket->sd.stat & LOCO_IN_USE) && (LnPacket->sd.spd)) + sendOPC_LOCO_SPD(LnPacket->sd.slot, 0); + } + + if(LnPacket->sd.slot >= MaxSlot) + CommandState = CMD_DONE; + break; + + case OPC_LOCO_SPD: + Serial.print("Set Slot: "); Serial.print(LnPacket->lsp.slot); + Serial.print(" : Speed: "); Serial.println(LnPacket->lsp.spd); + break; + } + } +} + +void setup() { + Serial.begin(115200); + Serial.println("\nLocoNet Controller"); + + // initialize the LocoNet interface + LocoNet.init(LNtxPort); +} + +char inChar = 0; +lnMsg sendPacket; + +void loop() { + // Check for any received LocoNet packets + while (lnMsg *LnPacket = LocoNet.receive() ) + { + processIncomingLoconetCommand( LnPacket ); + } + + if (Serial.available()) + { + inChar = Serial.read(); + + if (ValidCommands.indexOf(inChar) >= 0) + { + Serial.print("Command: "); Serial.println(inChar); + + if(inChar == 'o') // Track Power On + { + sendOPC_GP(1); + } + + else if(inChar == 'f') // Track Power Off + { + sendOPC_GP(0); + } + + else if(inChar == 'i') // Idle + { + sendOPC_IDLE(); + } + + else + { + if(inChar == 's') + CommandState = CMD_SPEED_ZERO; + + else if(inChar == 'c') + CommandState = CMD_SLOT_CLEAR; + + for (int slot = 0; slot <= MaxSlot; slot++) + { + sendOPC_RQ_SL_DATA(slot); + + while (lnMsg *LnPacket = LocoNet.receive() ) + processIncomingLoconetCommand( LnPacket ); + } + } + } + } +}