diff --git a/NmraDcc.cpp b/NmraDcc.cpp index 48ed11d..03e55da 100644 --- a/NmraDcc.cpp +++ b/NmraDcc.cpp @@ -26,6 +26,7 @@ // 2017-11-29 Ken West (kgw4449@gmail.com): // Minor fixes to pass NMRA Baseline Conformance Tests. // 2018-12-17 added ESP32 support by Trusty (thierry@lapajaparis.net) +// 2019-02-17 added ESP32 specific changes by Hans Tanner // //------------------------------------------------------------------------ // @@ -244,6 +245,9 @@ struct countOf_t countOf; #if defined ( __STM32F1__ ) static ExtIntTriggerMode ISREdge; +#elif defined ( ESP32 ) +static byte ISREdge; // Holder of the Next Edge we're looking for: RISING or FALLING +static byte ISRWatch; // Interrupt Handler Edge Filter #else static byte ISREdge; // RISING or FALLING #endif @@ -301,8 +305,37 @@ DCC_PROCESSOR_STATE ; DCC_PROCESSOR_STATE DccProcState ; +#ifdef ESP32 +portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; + +void IRAM_ATTR ExternalInterruptHandler(void) +#else void ExternalInterruptHandler(void) +#endif { +#ifdef ESP32 +// switch (ISRWatch) +// { +// case RISING: if (digitalRead(DccProcState.ExtIntPinNum)) break; +// case FALLING: if (digitalRead(DccProcState.ExtIntPinNum)) return; break; +// } + // First compare the edge we're looking for to the pin state + switch (ISRWatch) + { + case CHANGE: + break; + + case RISING: + if (digitalRead(DccProcState.ExtIntPinNum) != HIGH) + return; + break; + + case FALLING: + if (digitalRead(DccProcState.ExtIntPinNum) != LOW) + return; + break; + } +#endif // Bit evaluation without Timer 0 ------------------------------ uint8_t DccBitVal; static int8_t bit1, bit2 ; @@ -353,7 +386,11 @@ void ExternalInterruptHandler(void) #if defined ( __STM32F1__ ) detachInterrupt( DccProcState.ExtIntNum ); #endif + #ifdef ESP32 + ISRWatch = CHANGE; + #else attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, CHANGE); + #endif halfBit = 0; bitMax = MAX_ONEBITHALF; bitMin = MIN_ONEBITHALF; @@ -400,7 +437,11 @@ void ExternalInterruptHandler(void) #if defined ( __STM32F1__ ) detachInterrupt( DccProcState.ExtIntNum ); #endif + #ifdef ESP32 + ISRWatch = ISREdge; + #else attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge ); + #endif SET_TP3; CLR_TP4; } @@ -439,7 +480,11 @@ void ExternalInterruptHandler(void) #if defined ( __STM32F1__ ) detachInterrupt( DccProcState.ExtIntNum ); #endif + #ifdef ESP32 + ISRWatch = ISREdge; + #else attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge ); + #endif CLR_TP1; CLR_TP4; break; @@ -471,7 +516,11 @@ void ExternalInterruptHandler(void) #if defined ( __STM32F1__ ) detachInterrupt( DccProcState.ExtIntNum ); #endif + #ifdef ESP32 + ISRWatch = ISREdge; + #else attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge ); + #endif CLR_TP4; break; @@ -509,8 +558,14 @@ void ExternalInterruptHandler(void) DccRx.State = WAIT_PREAMBLE ; bitMax = MAX_PRAEAMBEL; bitMin = MIN_ONEBITFULL; +#ifdef ESP32 + portENTER_CRITICAL_ISR(&mux); +#endif DccRx.PacketCopy = DccRx.PacketBuf ; DccRx.DataReady = 1 ; +#ifdef ESP32 + portEXIT_CRITICAL_ISR(&mux); +#endif SET_TP3; } else // Get next Byte @@ -1326,16 +1381,22 @@ void NmraDcc::init( uint8_t ManufacturerId, uint8_t VersionId, uint8_t Flags, ui MODE_TP2; MODE_TP3; MODE_TP4; - ISREdge = RISING; bitMax = MAX_ONEBITFULL; bitMin = MIN_ONEBITFULL; - attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, RISING); DccProcState.Flags = Flags ; DccProcState.OpsModeAddressBaseCV = OpsModeAddressBaseCV ; DccProcState.myDccAddress = -1; DccProcState.inAccDecDCCAddrNextReceivedMode = 0; + ISREdge = RISING; + #ifdef ESP32 + ISRWatch = ISREdge; + attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, CHANGE); + #else + attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, RISING); + #endif + // Set the Bits that control Multifunction or Accessory behaviour // and if the Accessory decoder optionally handles Output Addressing // we need to peal off the top two bits @@ -1439,10 +1500,18 @@ uint8_t NmraDcc::process() { // We need to do this check with interrupts disabled //SET_TP4; +#ifdef ESP32 + portENTER_CRITICAL(&mux); +#else noInterrupts(); +#endif Msg = DccRx.PacketCopy ; DccRx.DataReady = 0 ; +#ifdef ESP32 + portEXIT_CRITICAL(&mux); +#else interrupts(); +#endif #ifdef DCC_DBGVAR countOf.Tel++; #endif diff --git a/library.properties b/library.properties index 0e6e49b..2622dbd 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=NmraDcc -version=2.0.0 -author=Alex Shepherd, Wolfgang Kuffer, Geoff Bunza, Martin Pischky, Franz-Peter Müller, Sven (littleyoda) +version=2.0.1 +author=Alex Shepherd, Wolfgang Kuffer, Geoff Bunza, Martin Pischky, Franz-Peter Müller, Sven (littleyoda), Hans Tanner maintainer=Alex Shepherd sentence=Enables NMRA DCC Communication paragraph=This library allows you to interface to a NMRA DCC track signal and receive DCC commands. The library has been tested on AVR ATTiny84/85 & ATMega88/168/328/32u4, ESP8266 and Teensy 3.x using the INT0/1 Hardware Interrupt and micros() ONLY and no longer uses Timer0 Compare Match B, which makes it much more portable to other platforms.