From b2497625505690353dc4e86fb59b43415e18da2d Mon Sep 17 00:00:00 2001 From: Alex Shepherd Date: Thu, 2 May 2019 21:42:59 +1200 Subject: [PATCH 1/5] changed the version to 201 in the header --- NmraDcc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NmraDcc.h b/NmraDcc.h index d1834c7..55bf4b4 100644 --- a/NmraDcc.h +++ b/NmraDcc.h @@ -49,7 +49,7 @@ #ifndef NMRADCC_IS_IN #define NMRADCC_IS_IN -#define NMRADCC_VERSION 200 // Version 2.0.0 +#define NMRADCC_VERSION 201 // Version 2.0.1 #define MAX_DCC_MESSAGE_LEN 6 // including XOR-Byte From 6d12e6cd3f5f520020d49946652a94c1e3473f6b Mon Sep 17 00:00:00 2001 From: Alex Shepherd Date: Sat, 25 May 2019 15:52:55 +1200 Subject: [PATCH 2/5] added conditional compilation for ESP8266 to add ICACHE_RAM_ATTR to ExternalInterruptHandler changed storage for Micros to unsigned long --- NmraDcc.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/NmraDcc.cpp b/NmraDcc.cpp index 6adfc6e..fa2561a 100644 --- a/NmraDcc.cpp +++ b/NmraDcc.cpp @@ -310,6 +310,8 @@ DCC_PROCESSOR_STATE DccProcState ; portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; void IRAM_ATTR ExternalInterruptHandler(void) +#elif defined(ESP8266) +void ICACHE_RAM_ATTR ExternalInterruptHandler(void) #else void ExternalInterruptHandler(void) #endif @@ -340,9 +342,9 @@ void ExternalInterruptHandler(void) // Bit evaluation without Timer 0 ------------------------------ uint8_t DccBitVal; static int8_t bit1, bit2 ; - static word lastMicros; + static unsigned long lastMicros = 0; static byte halfBit, DCC_IrqRunning; - unsigned int actMicros, bitMicros; + unsigned long actMicros, bitMicros; if ( DCC_IrqRunning ) { // nested DCC IRQ - obviously there are glitches // ignore this interrupt and increment glitchcounter From 6a7e206032b7f056c1d11131b5ed40cc91def61b Mon Sep 17 00:00:00 2001 From: Alex Shepherd Date: Mon, 5 Aug 2019 21:30:39 +1200 Subject: [PATCH 3/5] reverted changes around lastMicros --- NmraDcc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NmraDcc.cpp b/NmraDcc.cpp index fa2561a..4034f53 100644 --- a/NmraDcc.cpp +++ b/NmraDcc.cpp @@ -342,9 +342,9 @@ void ExternalInterruptHandler(void) // Bit evaluation without Timer 0 ------------------------------ uint8_t DccBitVal; static int8_t bit1, bit2 ; - static unsigned long lastMicros = 0; + static word lastMicros = 0; static byte halfBit, DCC_IrqRunning; - unsigned long actMicros, bitMicros; + unsigned int actMicros, bitMicros; if ( DCC_IrqRunning ) { // nested DCC IRQ - obviously there are glitches // ignore this interrupt and increment glitchcounter From e06f6b3bce9277de9f9b3b6e51b7bf91329f8c5a Mon Sep 17 00:00:00 2001 From: Alex Shepherd Date: Mon, 5 Aug 2019 21:34:48 +1200 Subject: [PATCH 4/5] bumped version to 2.0.2 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 2622dbd..ac7eec3 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=NmraDcc -version=2.0.1 +version=2.0.2 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 From f3a2b87693e724663a43959c922738c6f1dcb6ac Mon Sep 17 00:00:00 2001 From: Alex Shepherd Date: Tue, 6 Aug 2019 00:22:04 +1200 Subject: [PATCH 5/5] split out ServiceMode ackCV from Ops Mode AdvancedCVAck as doing a ackCV in Ops Mode is wrong and adds 6ms busy delay add cache of CV29 value --- NmraDcc.cpp | 35 ++++++++++++++++++++--------------- NmraDcc.h | 14 +++++++++++++- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/NmraDcc.cpp b/NmraDcc.cpp index 4034f53..334de28 100644 --- a/NmraDcc.cpp +++ b/NmraDcc.cpp @@ -295,7 +295,8 @@ typedef struct uint8_t ExtIntNum; uint8_t ExtIntPinNum; int16_t myDccAddress; // Cached value of DCC Address from CVs - uint8_t inAccDecDCCAddrNextReceivedMode; + uint8_t inAccDecDCCAddrNextReceivedMode; + uint8_t cv29Value; #ifdef DCC_DEBUG uint8_t IntCount; uint8_t TickCount; @@ -604,6 +605,13 @@ void ackCV(void) notifyCVAck() ; } +void ackAdvancedCV(void) +{ + if( notifyAdvancedCVAck && (DccProcState.cv29Value & CV29_ADV_ACK) ) + notifyAdvancedCVAck() ; +} + + uint8_t readEEPROM( unsigned int CV ) { return EEPROM.read(CV) ; } @@ -663,6 +671,7 @@ uint8_t writeCV( unsigned int CV, uint8_t Value) { case CV_29_CONFIG: // copy addressmode Bit to Flags + DccProcState.cv29Value = Value; DccProcState.Flags = ( DccProcState.Flags & ~FLAGS_CV29_BITS) | (Value & FLAGS_CV29_BITS); // no break, because myDccAdress must also be reset case CV_ACCESSORY_DECODER_ADDRESS_LSB: // Also same CV for CV_MULTIFUNCTION_PRIMARY_ADDRESS @@ -691,23 +700,19 @@ uint8_t writeCV( unsigned int CV, uint8_t Value) uint16_t getMyAddr(void) { - uint8_t CV29Value ; - if( DccProcState.myDccAddress != -1 ) // See if we can return the cached value return( DccProcState.myDccAddress ); - CV29Value = readCV( CV_29_CONFIG ) ; - - if( CV29Value & CV29_ACCESSORY_DECODER ) // Accessory Decoder? + if( DccProcState.cv29Value & CV29_ACCESSORY_DECODER ) // Accessory Decoder? { - if( CV29Value & CV29_OUTPUT_ADDRESS_MODE ) + if( DccProcState.cv29Value & CV29_OUTPUT_ADDRESS_MODE ) DccProcState.myDccAddress = ( readCV( CV_ACCESSORY_DECODER_ADDRESS_MSB ) << 8 ) | readCV( CV_ACCESSORY_DECODER_ADDRESS_LSB ); else DccProcState.myDccAddress = ( ( readCV( CV_ACCESSORY_DECODER_ADDRESS_MSB ) & 0b00000111) << 6 ) | ( readCV( CV_ACCESSORY_DECODER_ADDRESS_LSB ) & 0b00111111) ; } else // Multi-Function Decoder? { - if( CV29Value & CV29_EXT_ADDRESSING ) // Two Byte Address? + if( DccProcState.cv29Value & CV29_EXT_ADDRESSING ) // Two Byte Address? DccProcState.myDccAddress = ( ( readCV( CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB ) - 192 ) << 8 ) | readCV( CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB ) ; else @@ -728,7 +733,7 @@ void processDirectOpsOperation( uint8_t Cmd, uint16_t CVAddr, uint8_t Value ) if( validCV( CVAddr, 1 ) ) { if( writeCV( CVAddr, Value ) == Value ) - ackCV(); + ackAdvancedCV(); } } @@ -737,7 +742,7 @@ void processDirectOpsOperation( uint8_t Cmd, uint16_t CVAddr, uint8_t Value ) if( validCV( CVAddr, 0 ) ) { if( readCV( CVAddr ) == Value ) - ackCV(); + ackAdvancedCV(); } } } @@ -762,7 +767,7 @@ void processDirectOpsOperation( uint8_t Cmd, uint16_t CVAddr, uint8_t Value ) tempValue &= ~BitMask ; // Turn the Bit Off if( writeCV( CVAddr, tempValue ) == tempValue ) - ackCV() ; + ackAdvancedCV() ; } } @@ -774,12 +779,12 @@ void processDirectOpsOperation( uint8_t Cmd, uint16_t CVAddr, uint8_t Value ) if( BitValue ) { if( tempValue & BitMask ) - ackCV() ; + ackAdvancedCV() ; } else { if( !( tempValue & BitMask) ) - ackCV() ; + ackAdvancedCV() ; } } } @@ -873,7 +878,7 @@ void processMultiFunctionMessage( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t case 0b01100000: //TODO should we cache this info in DCC_PROCESSOR_STATE.Flags ? #ifdef NMRA_DCC_ENABLE_14_SPEED_STEP_MODE - speedSteps = (readCV( CV_29_CONFIG ) & CV29_F0_LOCATION) ? SPEED_STEP_28 : SPEED_STEP_14 ; + speedSteps = (DccProcState.cv29Value & CV29_F0_LOCATION) ? SPEED_STEP_28 : SPEED_STEP_14 ; #else speedSteps = SPEED_STEP_28 ; #endif @@ -1409,7 +1414,7 @@ void NmraDcc::init( uint8_t ManufacturerId, uint8_t VersionId, uint8_t Flags, ui // 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 - writeCV( CV_29_CONFIG, ( readCV( CV_29_CONFIG ) & ~FLAGS_CV29_BITS ) | (Flags & FLAGS_CV29_BITS) ) ; + DccProcState.cv29Value = writeCV( CV_29_CONFIG, ( readCV( CV_29_CONFIG ) & ~FLAGS_CV29_BITS ) | (Flags & FLAGS_CV29_BITS) ) ; uint8_t doAutoFactoryDefault = 0; if((Flags & FLAGS_AUTO_FACTORY_DEFAULT) && (readCV(CV_VERSION_ID) == 255) && (readCV(CV_MANUFACTURER_ID) == 255)) diff --git a/NmraDcc.h b/NmraDcc.h index 55bf4b4..cfc8f51 100644 --- a/NmraDcc.h +++ b/NmraDcc.h @@ -97,7 +97,7 @@ typedef struct #define CV_29_CONFIG 29 #if defined(ESP32) - #include + #include #define MAXCV SPI_FLASH_SEC_SIZE #elif defined(ESP8266) #include @@ -698,6 +698,18 @@ extern void notifyCVResetFactoryDefault(void) __attribute__ ((weak)); * None */ extern void notifyCVAck(void) __attribute__ ((weak)); +/*+ + * notifyAdvancedCVAck() Called when a CV write must be acknowledged. + * This callback must increase the current drawn by this + * decoder by at least 60mA for 6ms +/- 1ms. + * + * Inputs: + * None + * * + * Returns: + * None + */ +extern void notifyAdvancedCVAck(void) __attribute__ ((weak)); /*+ * notifyServiceMode(bool) Called when state of 'inServiceMode' changes *