Commanders
Arduino buttons/bus library
NmraDcc.cpp
1 //------------------------------------------------------------------------
2 //
3 // Model Railroading with Arduino - NmraDcc.cpp
4 //
5 // Copyright (c) 2008 - 2017 Alex Shepherd
6 //
7 // This source file is subject of the GNU general public license 2,
8 // that is available at the world-wide-web at
9 // http://www.gnu.org/licenses/gpl.txt
10 //
11 //------------------------------------------------------------------------
12 //
13 // file: NmraDcc.cpp
14 // author: Alex Shepherd
15 // webpage: http://mrrwa.org/
16 // history: 2008-03-20 Initial Version
17 // 2011-06-26 Migrated into Arduino library from OpenDCC codebase
18 // 2014 Added getAddr to NmraDcc Geoff Bunza
19 // 2015-11-06 Martin Pischky (martin@pischky.de):
20 // Experimental Version to support 14 speed steps
21 // and new signature of notifyDccSpeed and notifyDccFunc
22 // 2015-12-16 Version without use of Timer0 by Franz-Peter Müller
23 // 2016-07-16 handle glitches on DCC line
24 // 2016-08-20 added ESP8266 support by Sven (littleyoda)
25 // 2017-01-19 added STM32F1 support by Franz-Peter
26 // 2017-11-29 Ken West (kgw4449@gmail.com):
27 // Minor fixes to pass NMRA Baseline Conformance Tests.
28 // 2018-12-17 added ESP32 support by Trusty (thierry@lapajaparis.net)
29 //
30 //------------------------------------------------------------------------
31 //
32 // purpose: Provide a simplified interface to decode NMRA DCC packets
33 // and build DCC Mobile and Stationary Decoders
34 //
35 //------------------------------------------------------------------------
36 
37 #include "Commanders.h"
38 
39 #ifndef NO_DCCCOMMANDERNMRA
40 
41 #include "NmraDcc.h"
42 #ifdef __AVR_MEGA__
43 #include <avr/eeprom.h>
44 #endif
45 
46 // Uncomment to print DEBUG messages
47 //#define DEBUG_PRINT
48 
49 //------------------------------------------------------------------------
50 // DCC Receive Routine
51 //
52 // Howto: uses two interrupts: a rising edge in DCC polarity triggers INTx
53 // in INTx handler, Timer0 CompareB with a delay of 80us is started.
54 // On Timer0 CompareB Match the level of DCC is evaluated and
55 // parsed.
56 //
57 // |<-----116us----->|
58 //
59 // DCC 1: _________XXXXXXXXX_________XXXXXXXXX_________
60 // ^-INTx
61 // |----87us--->|
62 // ^Timer-INT: reads zero
63 //
64 // DCC 0: _________XXXXXXXXXXXXXXXXXX__________________
65 // ^-INTx
66 // |----------->|
67 // ^Timer-INT: reads one
68 //
69 // new DCC Receive Routine without Timer0 ........................................................
70 //
71 // Howto: uses only one interrupt at the rising or falling edge of the DCC signal
72 // The time between two edges is measured to determine the bit value
73 // Synchronizing to the edge of the first part of a bit is done after recognizing the start bit
74 // During synchronizing each part of a bit is detected ( Interruptmode 'change' )
75 //
76 // |<-----116us----->|
77 // DCC 1: _________XXXXXXXXX_________XXXXXXXXX_________
78 // |<--------146us------>|
79 // ^-INTx ^-INTx
80 // less than 138us: its a one-Bit
81 //
82 //
83 // |<-----------------232us----------->|
84 // DCC 0: _________XXXXXXXXXXXXXXXXXX__________________XXXXXXXX__________
85 // |<--------146us------->|
86 // ^-INTx ^-INTx
87 // greater than 138us: its a zero bit
88 //
89 //
90 //
91 //
92 //------------------------------------------------------------------------
93 
94 #define MAX_ONEBITFULL 146
95 #define MAX_PRAEAMBEL 146
96 #define MAX_ONEBITHALF 82
97 #define MIN_ONEBITFULL 82
98 #define MIN_ONEBITHALF 35
99 #define MAX_BITDIFF 18
100 
101 
102 // Debug-Ports
103 //#define debug // Testpulse for logic analyser
104 #ifdef debug
105  #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
106  #define MODE_TP1 DDRF |= (1<<2) //pinA2
107  #define SET_TP1 PORTF |= (1<<2)
108  #define CLR_TP1 PORTF &= ~(1<<2)
109  #define MODE_TP2 DDRF |= (1<<3) //pinA3
110  #define SET_TP2 PORTF |= (1<<3)
111  #define CLR_TP2 PORTF &= ~(1<<3)
112  #define MODE_TP3 DDRF |= (1<<4) //pinA4
113  #define SET_TP3 PORTF |= (1<<4)
114  #define CLR_TP3 PORTF &= ~(1<<4)
115  #define MODE_TP4 DDRF |= (1<<5) //pinA5
116  #define SET_TP4 PORTF |= (1<<5)
117  #define CLR_TP4 PORTF &= ~(1<<5)
118  #elif defined(__AVR_ATmega32U4__)
119  #define MODE_TP1 DDRF |= (1<<4) //A3
120  #define SET_TP1 PORTF |= (1<<4)
121  #define CLR_TP1 PORTF &= ~(1<<4)
122  #define MODE_TP2 DDRF |= (1<<5) //A2
123  #define SET_TP2 PORTF |= (1<<5)
124  #define CLR_TP2 PORTF &= ~(1<<5)
125  #define MODE_TP3
126  #define SET_TP3
127  #define CLR_TP3
128  #define MODE_TP4
129  #define SET_TP4
130  #define CLR_TP4
131  #elif defined(__AVR_ATmega328P__)
132  #define MODE_TP1 DDRC |= (1<<1) //A1
133  #define SET_TP1 PORTC |= (1<<1)
134  #define CLR_TP1 PORTC &= ~(1<<1)
135  #define MODE_TP2 DDRC |= (1<<2) // A2
136  #define SET_TP2 PORTC |= (1<<2)
137  #define CLR_TP2 PORTC &= ~(1<<2)
138  #define MODE_TP3 DDRC |= (1<<3) //A3
139  #define SET_TP3 PORTC |= (1<<3)
140  #define CLR_TP3 PORTC &= ~(1<<3)
141  #define MODE_TP4 DDRC |= (1<<4) //A4
142  #define SET_TP4 PORTC |= (1<<4)
143  #define CLR_TP4 PORTC &= ~(1<<4)
144  #elif defined(__arm__) && (defined(__MK20DX128__) || defined(__MK20DX256__))
145  // Teensys 3.x
146  #define MODE_TP1 pinMode( A1,OUTPUT ) // A1= PortC, Bit0
147  #define SET_TP1 GPIOC_PSOR = 0x01
148  #define CLR_TP1 GPIOC_PCOR = 0x01
149  #define MODE_TP2 pinMode( A2,OUTPUT ) // A2= PortB Bit0
150  #define SET_TP2 GPIOB_PSOR = 0x01
151  #define CLR_TP2 GPIOB_PCOR = 0x01
152  #define MODE_TP3 pinMode( A3,OUTPUT ) // A3 = PortB Bit1
153  #define SET_TP3 GPIOB_PSOR = 0x02
154  #define CLR_TP3 GPIOB_PCOR = 0x02
155  #define MODE_TP4 pinMode( A4,OUTPUT ) // A4 = PortB Bit3
156  #define SET_TP4 GPIOB_PSOR = 0x08
157  #define CLR_TP4 GPIOB_PCOR = 0x08
158  #elif defined (__STM32F1__)
159  // STM32F103...
160  #define MODE_TP1 pinMode( PB12,OUTPUT ) // TP1= PB12
161  #define SET_TP1 gpio_write_bit( GPIOB,12, HIGH );
162  #define CLR_TP1 gpio_write_bit( GPIOB,12, LOW );
163  #define MODE_TP2 pinMode( PB13,OUTPUT ) // TP2= PB13
164  #define SET_TP2 gpio_write_bit( GPIOB,13, HIGH );
165  #define CLR_TP2 gpio_write_bit( GPIOB,13, LOW );
166  #define MODE_TP3 pinMode( PB14,OUTPUT ) // TP3 = PB14
167  #define SET_TP3 gpio_write_bit( GPIOB,14, HIGH );
168  #define CLR_TP3 gpio_write_bit( GPIOB,14, LOW );
169  #define MODE_TP4 pinMode( PB15,OUTPUT ) // TP4 = PB15
170  #define SET_TP4 gpio_write_bit( GPIOB,15, HIGH );
171  #define CLR_TP4 gpio_write_bit( GPIOB,15, LOW );
172  #elif defined(ESP8266)
173  #define MODE_TP1 pinMode( D5,OUTPUT ) ; // GPIO 14
174  #define SET_TP1 GPOS = (1 << D5);
175  #define CLR_TP1 GPOC = (1 << D5);
176  #define MODE_TP2 pinMode( D6,OUTPUT ) ; // GPIO 12
177  #define SET_TP2 GPOS = (1 << D6);
178  #define CLR_TP2 GPOC = (1 << D6);
179  #define MODE_TP3 pinMode( D7,OUTPUT ) ; // GPIO 13
180  #define SET_TP3 GPOS = (1 << D7);
181  #define CLR_TP3 GPOC = (1 << D7);
182  #define MODE_TP4 pinMode( D8,OUTPUT ) ; // GPIO 15
183  #define SET_TP4 GPOC = (1 << D8);
184  #define CLR_TP4 GPOC = (1 << D8);
185  #elif defined(ESP32)
186  #define MODE_TP1 pinMode( 33,OUTPUT ) ; // GPIO 33
187  #define SET_TP1 GPOS = (1 << 33);
188  #define CLR_TP1 GPOC = (1 << 33);
189  #define MODE_TP2 pinMode( 25,OUTPUT ) ; // GPIO 25
190  #define SET_TP2 GPOS = (1 << 25);
191  #define CLR_TP2 GPOC = (1 << 25);
192  #define MODE_TP3 pinMode( 26,OUTPUT ) ; // GPIO 26
193  #define SET_TP3 GPOS = (1 << 26);
194  #define CLR_TP3 GPOC = (1 << 26);
195  #define MODE_TP4 pinMode( 27,OUTPUT ) ; // GPIO 27
196  #define SET_TP4 GPOC = (1 << 27);
197  #define CLR_TP4 GPOC = (1 << 27);
198 
199 
200  //#elif defined(__AVR_ATmega128__) ||defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
201  #else
202  #define MODE_TP1
203  #define SET_TP1
204  #define CLR_TP1
205  #define MODE_TP2
206  #define SET_TP2
207  #define CLR_TP2
208  #define MODE_TP3
209  #define SET_TP3
210  #define CLR_TP3
211  #define MODE_TP4
212  #define SET_TP4
213  #define CLR_TP4
214 
215  #endif
216 #else
217  #define MODE_TP1
218  #define SET_TP1
219  #define CLR_TP1
220  #define MODE_TP2
221  #define SET_TP2
222  #define CLR_TP2
223  //#define MODE_TP2 DDRC |= (1<<2) // A2
224  //#define SET_TP2 PORTC |= (1<<2)
225  //#define CLR_TP2 PORTC &= ~(1<<2)
226  #define MODE_TP3
227  #define SET_TP3
228  #define CLR_TP3
229  #define MODE_TP4
230  #define SET_TP4
231  #define CLR_TP4
232  //#define MODE_TP4 DDRC |= (1<<4) //A4
233  //#define SET_TP4 PORTC |= (1<<4)
234  //#define CLR_TP4 PORTC &= ~(1<<4)
235 
236 #endif
237 #ifdef DEBUG_PRINT
238  #define DB_PRINT( x, ... ) { char dbgbuf[80]; sprintf_P( dbgbuf, (const char*) F( x ) , ##__VA_ARGS__ ) ; Serial.println( dbgbuf ); }
239  #define DB_PRINT_( x, ... ) { char dbgbuf[80]; sprintf_P( dbgbuf, (const char*) F( x ) , ##__VA_ARGS__ ) ; Serial.print( dbgbuf ); }
240 #else
241  #define DB_PRINT( x, ... ) ;
242  #define DB_PRINT_( x, ... ) ;
243 #endif
244 
245 #ifdef DCC_DBGVAR
246 struct countOf_t countOf;
247 #endif
248 
249 #if defined ( __STM32F1__ )
250 static ExtIntTriggerMode ISREdge;
251 #else
252 static byte ISREdge; // RISING or FALLING
253 #endif
254 static word bitMax, bitMin;
255 
256 typedef enum
257 {
258  WAIT_PREAMBLE = 0,
259  WAIT_START_BIT,
260  WAIT_DATA,
261  WAIT_END_BIT
262 }
263 DccRxWaitState ;
264 
265 typedef enum
266 {
267  OPS_INS_RESERVED = 0,
268  OPS_INS_VERIFY_BYTE,
269  OPS_INS_BIT_MANIPULATION,
270  OPS_INS_WRITE_BYTE
271 }
272 OpsInstructionType;
273 
274 struct DccRx_t
275 {
276  DccRxWaitState State ;
277  uint8_t DataReady ;
278  uint8_t BitCount ;
279  uint8_t TempByte ;
280  DCC_MSG PacketBuf;
281  DCC_MSG PacketCopy;
282 }
283 DccRx ;
284 
285 typedef struct
286 {
287  uint8_t Flags ;
288  uint8_t OpsModeAddressBaseCV ;
289  uint8_t inServiceMode ;
290  long LastServiceModeMillis ;
291  uint8_t PageRegister ; // Used for Paged Operations in Service Mode Programming
292  uint8_t DuplicateCount ;
293  DCC_MSG LastMsg ;
294  uint8_t ExtIntNum;
295  uint8_t ExtIntPinNum;
296  int16_t myDccAddress; // Cached value of DCC Address from CVs
297  uint8_t inAccDecDCCAddrNextReceivedMode;
298 #ifdef DCC_DEBUG
299  uint8_t IntCount;
300  uint8_t TickCount;
301  uint8_t NestedIrqCount;
302 #endif
303 }
305 
306 DCC_PROCESSOR_STATE DccProcState ;
307 
308 void ExternalInterruptHandler(void)
309 {
310 // Bit evaluation without Timer 0 ------------------------------
311  uint8_t DccBitVal;
312  static int8_t bit1, bit2 ;
313  static word lastMicros;
314  static byte halfBit, DCC_IrqRunning;
315  unsigned int actMicros, bitMicros;
316  if ( DCC_IrqRunning ) {
317  // nested DCC IRQ - obviously there are glitches
318  // ignore this interrupt and increment glitchcounter
319  CLR_TP3;
320  #ifdef DCC_DEBUG
321  DccProcState.NestedIrqCount++;
322  #endif
323  SET_TP3;
324  return; //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> abort IRQ
325  }
326  SET_TP3;
327  actMicros = micros();
328  bitMicros = actMicros-lastMicros;
329  if ( bitMicros < bitMin ) {
330  // too short - my be false interrupt due to glitch or false protocol -> ignore
331  CLR_TP3;
332  SET_TP4; CLR_TP4;
333  return; //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> abort IRQ
334  }
335  DccBitVal = ( bitMicros < bitMax );
336  lastMicros = actMicros;
337  #ifdef debug
338  if(DccBitVal) {SET_TP2;} else {CLR_TP2;};
339  #endif
340  DCC_IrqRunning = true;
341  interrupts(); // time critical is only the micros() command,so allow nested irq's
342 #ifdef DCC_DEBUG
343  DccProcState.TickCount++;
344 #endif
345 
346  switch( DccRx.State )
347  {
348  case WAIT_PREAMBLE:
349  if( DccBitVal )
350  {
351  SET_TP1;
352  DccRx.BitCount++;
353  if( DccRx.BitCount > 10 ) {
354  DccRx.State = WAIT_START_BIT ;
355  // While waiting for the start bit, detect halfbit lengths. We will detect the correct
356  // sync and detect whether we see a false (e.g. motorola) protocol
357  #if defined ( __STM32F1__ )
358  detachInterrupt( DccProcState.ExtIntNum );
359  #endif
360  attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, CHANGE);
361  halfBit = 0;
362  bitMax = MAX_ONEBITHALF;
363  bitMin = MIN_ONEBITHALF;
364  CLR_TP1;
365  }
366  } else {
367  SET_TP1;
368  DccRx.BitCount = 0 ;
369  CLR_TP1;
370  }
371  break;
372 
373  case WAIT_START_BIT:
374  // we are looking for first half "0" bit after preamble
375  switch ( halfBit ) {
376  case 0: //SET_TP1;
377  // check first part
378  if ( DccBitVal ) {
379  // is still 1-bit (Preamble)
380  halfBit=1;
381  bit1=bitMicros;
382  } else {
383  // was "0" half bit, maybe the startbit
384  SET_TP1;
385  halfBit = 4;
386  CLR_TP1;
387  }
388  break;
389  case 1: //SET_TP1; // previous halfbit was '1'
390  if ( DccBitVal ) {
391  // its a '1' halfBit -> we are still in the preamble
392  halfBit = 0;
393  bit2=bitMicros;
394  DccRx.BitCount++;
395  if( abs(bit2-bit1) > MAX_BITDIFF ) {
396  // the length of the 2 halfbits differ too much -> wrong protokoll
397  CLR_TP2;
398  CLR_TP3;
399  DccRx.State = WAIT_PREAMBLE;
400  bitMax = MAX_PRAEAMBEL;
401  bitMin = MIN_ONEBITFULL;
402  DccRx.BitCount = 0;
403  SET_TP4;
404  #if defined ( __STM32F1__ )
405  detachInterrupt( DccProcState.ExtIntNum );
406  #endif
407  attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge );
408  SET_TP3;
409  CLR_TP4;
410  }
411  } else {
412  // first '0' half detected in second halfBit
413  // wrong sync or not a DCC protokoll
414  CLR_TP3;
415  halfBit = 3;
416  SET_TP3;
417  }
418  break;
419  case 3: //SET_TP1; // previous halfbit was '0' in second halfbit
420  if ( DccBitVal ) {
421  // its a '1' halfbit -> we got only a half '0' bit -> cannot be DCC
422  DccRx.State = WAIT_PREAMBLE;
423  bitMax = MAX_PRAEAMBEL;
424  bitMin = MIN_ONEBITFULL;
425  DccRx.BitCount = 0;
426  } else {
427  // we got two '0' halfbits -> it's the startbit
428  // but sync is NOT ok, change IRQ edge.
429  if ( ISREdge == RISING ) ISREdge = FALLING; else ISREdge = RISING;
430  DccRx.State = WAIT_DATA ;
431  bitMax = MAX_ONEBITFULL;
432  bitMin = MIN_ONEBITFULL;
433  DccRx.PacketBuf.Size = 0;
434  DccRx.PacketBuf.PreambleBits = 0;
435  for(uint8_t i = 0; i< MAX_DCC_MESSAGE_LEN; i++ )
436  DccRx.PacketBuf.Data[i] = 0;
437 
438  DccRx.PacketBuf.PreambleBits = DccRx.BitCount;
439  DccRx.BitCount = 0 ;
440  DccRx.TempByte = 0 ;
441  }
442  SET_TP4;
443  #if defined ( __STM32F1__ )
444  detachInterrupt( DccProcState.ExtIntNum );
445  #endif
446  attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge );
447  CLR_TP1;
448  CLR_TP4;
449  break;
450  case 4: SET_TP1; // previous (first) halfbit was 0
451  // if this halfbit is 0 too, we got the startbit
452  if ( DccBitVal ) {
453  // second halfbit is 1 -> unknown protokoll
454  DccRx.State = WAIT_PREAMBLE;
455  bitMax = MAX_PRAEAMBEL;
456  bitMin = MIN_ONEBITFULL;
457  DccRx.BitCount = 0;
458  } else {
459  // we got the startbit
460  DccRx.State = WAIT_DATA ;
461  bitMax = MAX_ONEBITFULL;
462  bitMin = MIN_ONEBITFULL;
463  DccRx.PacketBuf.Size = 0;
464  DccRx.PacketBuf.PreambleBits = 0;
465  for(uint8_t i = 0; i< MAX_DCC_MESSAGE_LEN; i++ )
466  DccRx.PacketBuf.Data[i] = 0;
467 
468  DccRx.PacketBuf.PreambleBits = DccRx.BitCount;
469  DccRx.BitCount = 0 ;
470  DccRx.TempByte = 0 ;
471  }
472 
473  CLR_TP1;
474  SET_TP4;
475  #if defined ( __STM32F1__ )
476  detachInterrupt( DccProcState.ExtIntNum );
477  #endif
478  attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge );
479  CLR_TP4;
480  break;
481 
482  }
483  break;
484 
485  case WAIT_DATA:
486  DccRx.BitCount++;
487  DccRx.TempByte = ( DccRx.TempByte << 1 ) ;
488  if( DccBitVal )
489  DccRx.TempByte |= 1 ;
490 
491  if( DccRx.BitCount == 8 )
492  {
493  if( DccRx.PacketBuf.Size == MAX_DCC_MESSAGE_LEN ) // Packet is too long - abort
494  {
495  DccRx.State = WAIT_PREAMBLE ;
496  bitMax = MAX_PRAEAMBEL;
497  bitMin = MIN_ONEBITFULL;
498  DccRx.BitCount = 0 ;
499  }
500  else
501  {
502  DccRx.State = WAIT_END_BIT ;
503  DccRx.PacketBuf.Data[ DccRx.PacketBuf.Size++ ] = DccRx.TempByte ;
504  }
505  }
506  break;
507 
508  case WAIT_END_BIT:
509  DccRx.BitCount++;
510  if( DccBitVal ) // End of packet?
511  {
512  CLR_TP3;
513  DccRx.State = WAIT_PREAMBLE ;
514  bitMax = MAX_PRAEAMBEL;
515  bitMin = MIN_ONEBITFULL;
516  DccRx.PacketCopy = DccRx.PacketBuf ;
517  DccRx.DataReady = 1 ;
518  SET_TP3;
519  }
520  else // Get next Byte
521  // KGW - Abort immediately if packet is too long.
522  if( DccRx.PacketBuf.Size == MAX_DCC_MESSAGE_LEN ) // Packet is too long - abort
523  {
524  DccRx.State = WAIT_PREAMBLE ;
525  bitMax = MAX_PRAEAMBEL;
526  bitMin = MIN_ONEBITFULL;
527  DccRx.BitCount = 0 ;
528  }
529  else
530  {
531  DccRx.State = WAIT_DATA ;
532 
533  DccRx.BitCount = 0 ;
534  DccRx.TempByte = 0 ;
535  }
536  }
537  CLR_TP1;
538  CLR_TP3;
539  DCC_IrqRunning = false;
540 }
541 
542 void ackCV(void)
543 {
544  if( notifyCVAck )
545  notifyCVAck() ;
546 }
547 
548 uint8_t readEEPROM( unsigned int CV ) {
549  return EEPROM.read(CV) ;
550 }
551 
552 void writeEEPROM( unsigned int CV, uint8_t Value ) {
553  EEPROM.write(CV, Value) ;
554  #if defined(ESP8266)
555  EEPROM.commit();
556  #endif
557  #if defined(ESP32)
558  EEPROM.commit();
559  #endif
560 }
561 
562 bool readyEEPROM() {
563  #ifdef __AVR_MEGA__
564  return eeprom_is_ready();
565  #else
566  return true;
567  #endif
568 }
569 
570 
571 uint8_t validCV( uint16_t CV, uint8_t Writable )
572 {
573  if( notifyCVResetFactoryDefault && (CV == CV_MANUFACTURER_ID ) && Writable )
574  notifyCVResetFactoryDefault();
575 
576  if( notifyCVValid )
577  return notifyCVValid( CV, Writable ) ;
578 
579  uint8_t Valid = 1 ;
580 
581  if( CV > MAXCV )
582  Valid = 0 ;
583 
584  if( Writable && ( ( CV ==CV_VERSION_ID ) || (CV == CV_MANUFACTURER_ID ) ) )
585  Valid = 0 ;
586 
587  return Valid ;
588 }
589 
590 uint8_t readCV( unsigned int CV )
591 {
592  uint8_t Value ;
593 
594  if( notifyCVRead )
595  return notifyCVRead( CV ) ;
596 
597  Value = readEEPROM(CV);
598  return Value ;
599 }
600 
601 uint8_t writeCV( unsigned int CV, uint8_t Value)
602 {
603  switch( CV )
604  {
605  case CV_29_CONFIG:
606  // copy addressmode Bit to Flags
607  DccProcState.Flags = ( DccProcState.Flags & ~~FLAGS_CV29_BITS) | (Value & FLAGS_CV29_BITS);
608  // no break, because myDccAdress must also be reset
609  case CV_ACCESSORY_DECODER_ADDRESS_LSB: // Also same CV for CV_MULTIFUNCTION_PRIMARY_ADDRESS
610  case CV_ACCESSORY_DECODER_ADDRESS_MSB:
611  case CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB:
612  case CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB:
613  DccProcState.myDccAddress = -1; // Assume any CV Write Operation might change the Address
614  }
615 
616  if( notifyCVWrite )
617  return notifyCVWrite( CV, Value ) ;
618 
619  if( readEEPROM( CV ) != Value )
620  {
621  writeEEPROM( CV, Value ) ;
622 
623  if( notifyCVChange )
624  notifyCVChange( CV, Value) ;
625 
626  if( notifyDccCVChange && !(DccProcState.Flags & FLAGS_SETCV_CALLED) )
627  notifyDccCVChange( CV, Value );
628  }
629 
630  return readEEPROM( CV ) ;
631 }
632 
633 uint16_t getMyAddr(void)
634 {
635  uint8_t CV29Value ;
636 
637  if( DccProcState.myDccAddress != -1 ) // See if we can return the cached value
638  return( DccProcState.myDccAddress );
639 
640  CV29Value = readCV( CV_29_CONFIG ) ;
641 
642  if( CV29Value & CV29_ACCESSORY_DECODER ) // Accessory Decoder?
643  {
644  if( CV29Value & CV29_OUTPUT_ADDRESS_MODE )
645  DccProcState.myDccAddress = ( readCV( CV_ACCESSORY_DECODER_ADDRESS_MSB ) << 8 ) | readCV( CV_ACCESSORY_DECODER_ADDRESS_LSB );
646  else
647  DccProcState.myDccAddress = ( ( readCV( CV_ACCESSORY_DECODER_ADDRESS_MSB ) & 0b00000111) << 6 ) | ( readCV( CV_ACCESSORY_DECODER_ADDRESS_LSB ) & 0b00111111) ;
648  }
649  else // Multi-Function Decoder?
650  {
651  if( CV29Value & CV29_EXT_ADDRESSING ) // Two Byte Address?
652  DccProcState.myDccAddress = ( ( readCV( CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB ) - 192 ) << 8 ) | readCV( CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB ) ;
653 
654  else
655  DccProcState.myDccAddress = readCV( 1 ) ;
656  }
657 
658  return DccProcState.myDccAddress ;
659 }
660 
661 void processDirectOpsOperation( uint8_t Cmd, uint16_t CVAddr, uint8_t Value )
662 {
663  // is it a Byte Operation
664  if( Cmd & 0x04 )
665  {
666  // Perform the Write Operation
667  if( Cmd & 0x08 )
668  {
669  if( validCV( CVAddr, 1 ) )
670  {
671  if( writeCV( CVAddr, Value ) == Value )
672  ackCV();
673  }
674  }
675 
676  else // Perform the Verify Operation
677  {
678  if( validCV( CVAddr, 0 ) )
679  {
680  if( readCV( CVAddr ) == Value )
681  ackCV();
682  }
683  }
684  }
685  // Perform the Bit-Wise Operation
686  else
687  {
688  uint8_t BitMask = (1 << (Value & 0x07) ) ;
689  uint8_t BitValue = Value & 0x08 ;
690  uint8_t BitWrite = Value & 0x10 ;
691 
692  uint8_t tempValue = readCV( CVAddr ) ; // Read the Current CV Value
693 
694  // Perform the Bit Write Operation
695  if( BitWrite )
696  {
697  if( validCV( CVAddr, 1 ) )
698  {
699  if( BitValue )
700  tempValue |= BitMask ; // Turn the Bit On
701 
702  else
703  tempValue &= ~~BitMask ; // Turn the Bit Off
704 
705  if( writeCV( CVAddr, tempValue ) == tempValue )
706  ackCV() ;
707  }
708  }
709 
710  // Perform the Bit Verify Operation
711  else
712  {
713  if( validCV( CVAddr, 0 ) )
714  {
715  if( BitValue )
716  {
717  if( tempValue & BitMask )
718  ackCV() ;
719  }
720  else
721  {
722  if( !( tempValue & BitMask) )
723  ackCV() ;
724  }
725  }
726  }
727  }
728 }
729 
731 #ifdef NMRA_DCC_PROCESS_MULTIFUNCTION
732 void processMultiFunctionMessage( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Cmd, uint8_t Data1, uint8_t Data2 )
733 {
734  uint8_t speed ;
735  uint16_t CVAddr ;
736  DCC_DIRECTION dir ;
737  DCC_SPEED_STEPS speedSteps ;
738 
739  uint8_t CmdMasked = Cmd & 0b11100000 ;
740 
741  // If we are an Accessory Decoder
742  if( DccProcState.Flags & FLAGS_DCC_ACCESSORY_DECODER )
743  {
744  // and this isn't an Ops Mode Write or we are NOT faking the Multifunction Ops mode address in CV 33+34 or
745  // it's not our fake address, then return
746  if( ( CmdMasked != 0b11100000 ) || ( DccProcState.OpsModeAddressBaseCV == 0 ) )
747  return ;
748 
749  uint16_t FakeOpsAddr = readCV( DccProcState.OpsModeAddressBaseCV ) | ( readCV( DccProcState.OpsModeAddressBaseCV + 1 ) << 8 ) ;
750  uint16_t OpsAddr = Addr & 0x3FFF ;
751 
752  if( OpsAddr != FakeOpsAddr )
753  return ;
754  }
755 
756  // We are looking for FLAGS_MY_ADDRESS_ONLY but it does not match and it is not a Broadcast Address then return
757  else if( ( DccProcState.Flags & FLAGS_MY_ADDRESS_ONLY ) && ( Addr != getMyAddr() ) && ( Addr != 0 ) )
758  return ;
759 
760  switch( CmdMasked )
761  {
762  case 0b00000000: // Decoder Control
763  switch( Cmd & 0b00001110 )
764  {
765  case 0b00000000:
766  if( notifyDccReset && ( Cmd & 0b00000001 ) ) // Hard Reset
767  if( notifyDccReset)
768  notifyDccReset( 1 ) ;
769  break ;
770 
771  case 0b00000010: // Factory Test
772  break ;
773 
774  case 0b00000110: // Set Decoder Flags
775  break ;
776 
777  case 0b00001010: // Set Advanced Addressing
778  break ;
779 
780  case 0b00001110: // Decoder Acknowledgment
781  break ;
782 
783  default: // Reserved
784  ;
785  }
786  break ;
787 
788  case 0b00100000: // Advanced Operations
789  switch( Cmd & 0b00011111 )
790  {
791  case 0b00011111:
792  if( notifyDccSpeed )
793  {
794  switch( Data1 & 0b01111111 )
795  {
796  case 0b00000000: // 0=STOP
797  speed = 1 ; // => 1
798  break ;
799 
800  case 0b00000001: // 1=EMERGENCY_STOP
801  speed = 0 ; // => 0
802  break ;
803 
804  default: // 2..127
805  speed = (Data1 & 0b01111111) ;
806  }
807  dir = (DCC_DIRECTION) ((Data1 & 0b10000000) >> 7) ;
808  notifyDccSpeed( Addr, AddrType, speed, dir, SPEED_STEP_128 ) ;
809  }
810  }
811  break;
812 
813  case 0b01000000:
814  case 0b01100000:
815  //TODO should we cache this info in DCC_PROCESSOR_STATE.Flags ?
816 #ifdef NMRA_DCC_ENABLE_14_SPEED_STEP_MODE
817  speedSteps = (readCV( CV_29_CONFIG ) & CV29_F0_LOCATION) ? SPEED_STEP_28 : SPEED_STEP_14 ;
818 #else
819  speedSteps = SPEED_STEP_28 ;
820 #endif
821  if( notifyDccSpeed )
822  {
823  switch( Cmd & 0b00011111 )
824  {
825  case 0b00000000: // 0 0000 = STOP
826  case 0b00010000: // 1 0000 = STOP
827  speed = 1 ; // => 1
828  break ;
829 
830  case 0b00000001: // 0 0001 = EMERGENCY STOP
831  case 0b00010001: // 1 0001 = EMERGENCY STOP
832  speed = 0 ; // => 0
833  break ;
834 
835  default:
836 #ifdef NMRA_DCC_ENABLE_14_SPEED_STEP_MODE
837  if( speedSteps == SPEED_STEP_14 )
838  {
839  speed = (Cmd & 0b00001111) ; // => 2..15
840  }
841  else
842  {
843 #endif
844  speed = (((Cmd & 0b00001111) << 1 ) | ((Cmd & 0b00010000) >> 4)) - 2 ; // => 2..29
845 #ifdef NMRA_DCC_ENABLE_14_SPEED_STEP_MODE
846  }
847 #endif
848  }
849  dir = (DCC_DIRECTION) ((Cmd & 0b00100000) >> 5) ;
850  notifyDccSpeed( Addr, AddrType, speed, dir, speedSteps ) ;
851  }
852  if( notifyDccSpeedRaw )
853  notifyDccSpeedRaw(Addr, AddrType, Cmd );
854 
855 #ifdef NMRA_DCC_ENABLE_14_SPEED_STEP_MODE
856  if( notifyDccFunc && (speedSteps == SPEED_STEP_14) )
857  {
858  // function light is controlled by this package
859  uint8_t fn0 = (Cmd & 0b00010000) ;
860  notifyDccFunc( Addr, AddrType, FN_0, fn0 ) ;
861  }
862 #endif
863  break;
864 
865  case 0b10000000: // Function Group 0..4
866  if( notifyDccFunc )
867  {
868  // function light is controlled by this package (28 or 128 speed steps)
869  notifyDccFunc( Addr, AddrType, FN_0_4, Cmd & 0b00011111 ) ;
870  }
871  break;
872 
873  case 0b10100000: // Function Group 5..8
874  if( notifyDccFunc)
875  {
876  if (Cmd & 0b00010000 )
877  notifyDccFunc( Addr, AddrType, FN_5_8, Cmd & 0b00001111 ) ;
878  else
879  notifyDccFunc( Addr, AddrType, FN_9_12, Cmd & 0b00001111 ) ;
880  }
881  break;
882 
883  case 0b11000000: // Feature Expansion Instruction
884  switch(Cmd & 0b00011111)
885  {
886  case 0b00011110:
887  if( notifyDccFunc )
888  notifyDccFunc( Addr, AddrType, FN_13_20, Data1 ) ;
889  break;
890 
891  case 0b00011111:
892  if( notifyDccFunc )
893  notifyDccFunc( Addr, AddrType, FN_21_28, Data1 ) ;
894  break;
895  }
896  break;
897 
898  case 0b11100000: // CV Access
899  CVAddr = ( ( ( Cmd & 0x03 ) << 8 ) | Data1 ) + 1 ;
900 
901  processDirectOpsOperation( Cmd, CVAddr, Data2 ) ;
902  break;
903  }
904 }
905 #endif
906 
908 #ifdef NMRA_DCC_PROCESS_SERVICEMODE
909 void processServiceModeOperation( DCC_MSG * pDccMsg )
910 {
911  uint16_t CVAddr ;
912  uint8_t Value ;
913  if( pDccMsg->Size == 3) // 3 Byte Packets are for Address Only, Register and Paged Mode
914  {
915  uint8_t RegisterAddr ;
916  DB_PRINT("3-BytePkt");
917  RegisterAddr = pDccMsg->Data[0] & 0x07 ;
918  Value = pDccMsg->Data[1] ;
919 
920  if( RegisterAddr == 5 )
921  {
922  DccProcState.PageRegister = Value ;
923  ackCV();
924  }
925 
926  else
927  {
928  if( RegisterAddr == 4 )
929  CVAddr = CV_29_CONFIG ;
930 
931  else if( ( RegisterAddr <= 3 ) && ( DccProcState.PageRegister > 0 ) )
932  CVAddr = ( ( DccProcState.PageRegister - 1 ) * 4 ) + RegisterAddr + 1 ;
933 
934  else
935  CVAddr = RegisterAddr + 1 ;
936 
937  if( pDccMsg->Data[0] & 0x08 ) // Perform the Write Operation
938  {
939  if( validCV( CVAddr, 1 ) )
940  {
941  if( writeCV( CVAddr, Value ) == Value )
942  ackCV();
943  }
944  }
945 
946  else // Perform the Verify Operation
947  {
948  if( validCV( CVAddr, 0 ) )
949  {
950  if( readCV( CVAddr ) == Value )
951  ackCV();
952  }
953  }
954  }
955  }
956 
957  else if( pDccMsg->Size == 4) // 4 Byte Packets are for Direct Byte & Bit Mode
958  {
959  DB_PRINT("BB-Mode");
960  CVAddr = ( ( ( pDccMsg->Data[0] & 0x03 ) << 8 ) | pDccMsg->Data[1] ) + 1 ;
961  Value = pDccMsg->Data[2] ;
962 
963  processDirectOpsOperation( pDccMsg->Data[0] & 0b00001100, CVAddr, Value ) ;
964  }
965 }
966 #endif
967 
969 void resetServiceModeTimer(uint8_t inServiceMode)
970 {
971  if (notifyServiceMode && inServiceMode != DccProcState.inServiceMode)
972  {
973  notifyServiceMode(inServiceMode);
974  }
975  // Set the Service Mode
976  DccProcState.inServiceMode = inServiceMode ;
977 
978  DccProcState.LastServiceModeMillis = inServiceMode ? millis() : 0 ;
979  if (notifyServiceMode && inServiceMode != DccProcState.inServiceMode)
980  {
981  notifyServiceMode(inServiceMode);
982  }
983 }
984 
986 void clearDccProcState(uint8_t inServiceMode)
987 {
988  resetServiceModeTimer( inServiceMode ) ;
989 
990  // Set the Page Register to it's default of 1 only on the first Reset
991  DccProcState.PageRegister = 1 ;
992 
993  // Clear the LastMsg buffer and DuplicateCount in preparation for possible CV programming
994  DccProcState.DuplicateCount = 0 ;
995  memset( &DccProcState.LastMsg, 0, sizeof( DCC_MSG ) ) ;
996 }
997 
999 #ifdef DEBUG_PRINT
1000 void SerialPrintPacketHex(const __FlashStringHelper *strLabel, DCC_MSG * pDccMsg)
1001 {
1002  Serial.print( strLabel );
1003 
1004  for( uint8_t i = 0; i < pDccMsg->Size; i++ )
1005  {
1006  if( pDccMsg->Data[i] <= 9)
1007  Serial.print('0');
1008 
1009  Serial.print( pDccMsg->Data[i], HEX );
1010  Serial.write( ' ' );
1011  }
1012  Serial.println();
1013 }
1014 #endif
1015 
1017 void execDccProcessor( DCC_MSG * pDccMsg )
1018 {
1019  if( ( pDccMsg->Data[0] == 0 ) && ( pDccMsg->Data[1] == 0 ) )
1020  {
1021  if( notifyDccReset )
1022  notifyDccReset( 0 ) ;
1023 
1024 #ifdef NMRA_DCC_PROCESS_SERVICEMODE
1025  // If this is the first Reset then perform some one-shot actions as we maybe about to enter service mode
1026  if( DccProcState.inServiceMode )
1027  resetServiceModeTimer( 1 ) ;
1028  else
1029  clearDccProcState( 1 );
1030 #endif
1031  }
1032 
1033  else
1034  {
1035 #ifdef NMRA_DCC_PROCESS_SERVICEMODE
1036  if( DccProcState.inServiceMode && ( pDccMsg->Data[0] >= 112 ) && ( pDccMsg->Data[0] < 128 ) )
1037  {
1038  resetServiceModeTimer( 1 ) ;
1039 
1040  if( memcmp( pDccMsg, &DccProcState.LastMsg, sizeof( DCC_MSG ) ) )
1041  {
1042  DccProcState.DuplicateCount = 0 ;
1043  memcpy( &DccProcState.LastMsg, pDccMsg, sizeof( DCC_MSG ) ) ;
1044  }
1045  // Wait until you see 2 identicle packets before acting on a Service Mode Packet
1046  else
1047  {
1048  DccProcState.DuplicateCount++ ;
1049  processServiceModeOperation( pDccMsg ) ;
1050  }
1051  }
1052 
1053  else
1054  {
1055  if( DccProcState.inServiceMode )
1056  clearDccProcState( 0 );
1057 #endif
1058 
1059  // Idle Packet
1060  if( ( pDccMsg->Data[0] == 0b11111111 ) && ( pDccMsg->Data[1] == 0 ) )
1061  {
1062  if( notifyDccIdle )
1063  notifyDccIdle() ;
1064  }
1065 
1066 #ifdef NMRA_DCC_PROCESS_MULTIFUNCTION
1067  // Multi Function Decoders (7-bit address)
1068  else if( pDccMsg->Data[0] < 128 )
1069  processMultiFunctionMessage( pDccMsg->Data[0], DCC_ADDR_SHORT, pDccMsg->Data[1], pDccMsg->Data[2], pDccMsg->Data[3] ) ;
1070 
1071  // Basic Accessory Decoders (9-bit) & Extended Accessory Decoders (11-bit)
1072  else if( pDccMsg->Data[0] < 192 )
1073 #else
1074  else if( ( pDccMsg->Data[0] >= 128 ) && ( pDccMsg->Data[0] < 192 ) )
1075 #endif
1076  {
1077  if( DccProcState.Flags & FLAGS_DCC_ACCESSORY_DECODER )
1078  {
1079  int16_t BoardAddress ;
1080  int16_t OutputAddress ;
1081  uint8_t TurnoutPairIndex ;
1082 
1083 #ifdef DEBUG_PRINT
1084  SerialPrintPacketHex(F( "eDP: AccCmd: "), pDccMsg);
1085 #endif
1086 
1087  BoardAddress = ( ( (~~pDccMsg->Data[1]) & 0b01110000 ) << 2 ) | ( pDccMsg->Data[0] & 0b00111111 ) ;
1088  TurnoutPairIndex = (pDccMsg->Data[1] & 0b00000110) >> 1;
1089  DB_PRINT("eDP: BAddr:%d, Index:%d", BoardAddress, TurnoutPairIndex);
1090 
1091  // First check for Legacy Accessory Decoder Configuration Variable Access Instruction
1092  // as it's got a different format to the others
1093  if((pDccMsg->Size == 5) && ((pDccMsg->Data[1] & 0b10001100) == 0b00001100))
1094  {
1095  DB_PRINT( "eDP: Legacy Accessory Decoder CV Access Command");
1096  // Check if this command is for our address or the broadcast address
1097  if((BoardAddress != getMyAddr()) && ( BoardAddress < 511 ))
1098  {
1099  DB_PRINT("eDP: Board Address Not Matched");
1100  return;
1101  }
1102 
1103  uint16_t cvAddress = ((pDccMsg->Data[1] & 0b00000011) << 8) + pDccMsg->Data[2] + 1;
1104  uint8_t cvValue = pDccMsg->Data[3];
1105  DB_PRINT("eDP: CV:%d Value:%d", cvAddress, cvValue );
1106  if(validCV( cvAddress, 1 ))
1107  writeCV(cvAddress, cvValue);
1108  return;
1109  }
1110 
1111 
1112  OutputAddress = (((BoardAddress - 1) << 2 ) | TurnoutPairIndex) + 1 ; //decoder output addresses start with 1, packet address range starts with 0
1113  // ( according to NMRA 9.2.2 )
1114  DB_PRINT("eDP: OAddr:%d", OutputAddress);
1115 
1116  if( DccProcState.inAccDecDCCAddrNextReceivedMode)
1117  {
1118  if( DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE )
1119  {
1120  DB_PRINT("eDP: Set OAddr:%d", OutputAddress);
1121  //uint16_t storedOutputAddress = OutputAddress + 1; // The value stored in CV1 & 9 for Output Addressing Mode is + 1
1122  writeCV(CV_ACCESSORY_DECODER_ADDRESS_LSB, (uint8_t)(OutputAddress % 256));
1123  writeCV(CV_ACCESSORY_DECODER_ADDRESS_MSB, (uint8_t)(OutputAddress / 256));
1124 
1125  if( notifyDccAccOutputAddrSet )
1126  notifyDccAccOutputAddrSet(OutputAddress);
1127  }
1128  else
1129  {
1130  DB_PRINT("eDP: Set BAddr:%d", BoardAddress);
1131  writeCV(CV_ACCESSORY_DECODER_ADDRESS_LSB, (uint8_t)(BoardAddress % 64));
1132  writeCV(CV_ACCESSORY_DECODER_ADDRESS_MSB, (uint8_t)(BoardAddress / 64));
1133 
1134  if( notifyDccAccBoardAddrSet )
1135  notifyDccAccBoardAddrSet(BoardAddress);
1136  }
1137 
1138  DccProcState.inAccDecDCCAddrNextReceivedMode = 0; // Reset the mode now that we have set the address
1139  }
1140 
1141  // If we're filtering addresses, does the address match our address or is it a broadcast address? If NOT then return
1142  if( DccProcState.Flags & FLAGS_MY_ADDRESS_ONLY )
1143  {
1144  if( DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE ) {
1145  DB_PRINT(" AddrChk: OAddr:%d, BAddr:%d, myAddr:%d Chk=%d", OutputAddress, BoardAddress, getMyAddr(), OutputAddress != getMyAddr() );
1146  if ( OutputAddress != getMyAddr() && OutputAddress < 2045 ) {
1147  DB_PRINT(" eDP: OAddr:%d, myAddr:%d - no match", OutputAddress, getMyAddr() );
1148  return;
1149  }
1150  } else {
1151  if( ( BoardAddress != getMyAddr() ) && ( BoardAddress < 511 ) ) {
1152  DB_PRINT(" eDP: BAddr:%d, myAddr:%d - no match", BoardAddress, getMyAddr() );
1153  return;
1154  }
1155  }
1156  DB_PRINT("eDP: Address Matched");
1157  }
1158 
1159 
1160  if((pDccMsg->Size == 4) && ((pDccMsg->Data[1] & 0b10001001) == 1)) // Extended Accessory Decoder Control Packet Format
1161  {
1162  // According to the NMRA Dcc Spec the Signal State should only use the lower 5 Bits,
1163  // however some manufacturers seem to allow/use all 8 bits, so we'll relax that constraint for now
1164  uint8_t state = pDccMsg->Data[2] ;
1165  DB_PRINT("eDP: OAddr:%d Extended State:%0X", OutputAddress, state);
1166  if( notifyDccSigOutputState )
1167  notifyDccSigOutputState(OutputAddress, state);
1168 
1169  // old callback ( for compatibility with 1.4.2, not to be used in new designs )
1170  if( notifyDccSigState )
1171  notifyDccSigState( OutputAddress, TurnoutPairIndex, pDccMsg->Data[2] ) ;
1172  }
1173 
1174  else if(pDccMsg->Size == 3) // Basic Accessory Decoder Packet Format
1175  {
1176  uint8_t direction = pDccMsg->Data[1] & 0b00000001;
1177  uint8_t outputPower = (pDccMsg->Data[1] & 0b00001000) >> 3;
1178 
1179  // old callback ( for compatibility with 1.4.2, not to be used in new designs )
1180  if ( notifyDccAccState )
1181  notifyDccAccState( OutputAddress, BoardAddress, pDccMsg->Data[1] & 0b00000111, outputPower );
1182 
1183  if( DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE )
1184  {
1185  DB_PRINT("eDP: OAddr:%d Turnout Dir:%d Output Power:%d", OutputAddress, direction, outputPower);
1186  if( notifyDccAccTurnoutOutput )
1187  notifyDccAccTurnoutOutput( OutputAddress, direction, outputPower );
1188  }
1189  else
1190  {
1191  DB_PRINT("eDP: Turnout Pair Index:%d Dir:%d Output Power: ", TurnoutPairIndex, direction, outputPower);
1192  if( notifyDccAccTurnoutBoard )
1193  notifyDccAccTurnoutBoard( BoardAddress, TurnoutPairIndex, direction, outputPower );
1194  }
1195  }
1196  else if(pDccMsg->Size == 6) // Accessory Decoder OPS Mode Programming
1197  {
1198  DB_PRINT("eDP: OPS Mode CV Programming Command");
1199  // Check for unsupported OPS Mode Addressing mode
1200  if(((pDccMsg->Data[1] & 0b10001001) != 1) && ((pDccMsg->Data[1] & 0b10001111) != 0x80))
1201  {
1202  DB_PRINT("eDP: Unsupported OPS Mode CV Addressing Mode");
1203  return;
1204  }
1205 
1206  // Check if this command is for our address or the broadcast address
1207  if(DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE)
1208  {
1209  DB_PRINT("eDP: Check Output Address:%d", OutputAddress);
1210  if((OutputAddress != getMyAddr()) && ( OutputAddress < 2045 ))
1211  {
1212  DB_PRINT("eDP: Output Address Not Matched");
1213  return;
1214  }
1215  }
1216  else
1217  {
1218  DB_PRINT("eDP: Check Board Address:%d", BoardAddress);
1219  if((BoardAddress != getMyAddr()) && ( BoardAddress < 511 ))
1220  {
1221  DB_PRINT("eDP: Board Address Not Matched");
1222  return;
1223  }
1224  }
1225 
1226  uint16_t cvAddress = ((pDccMsg->Data[2] & 0b00000011) << 8) + pDccMsg->Data[3] + 1;
1227  uint8_t cvValue = pDccMsg->Data[4];
1228 
1229  OpsInstructionType insType = (OpsInstructionType)((pDccMsg->Data[2] & 0b00001100) >> 2) ;
1230 
1231  DB_PRINT("eDP: OPS Mode Instruction:%d", insType);
1232  switch(insType)
1233  {
1234  case OPS_INS_RESERVED:
1235  case OPS_INS_VERIFY_BYTE:
1236  DB_PRINT("eDP: Unsupported OPS Mode Instruction:%d", insType);
1237  break; // We only support Write Byte or Bit Manipulation
1238 
1239  case OPS_INS_WRITE_BYTE:
1240  DB_PRINT("eDP: CV:%d Value:%d", cvAddress, cvValue);
1241  if(validCV( cvAddress, 1 ))
1242  writeCV(cvAddress, cvValue);
1243  break;
1244 
1245  // 111CDBBB
1246  // Where BBB represents the bit position within the CV,
1247  // D contains the value of the bit to be verified or written,
1248  // and C describes whether the operation is a verify bit or a write bit operation.
1249  // C = "1" WRITE BIT
1250  // C = "0" VERIFY BIT
1251  case OPS_INS_BIT_MANIPULATION:
1252  // Make sure its a Write Bit Manipulation
1253  if((cvValue & 0b00010000) && validCV(cvAddress, 1 ))
1254  {
1255  uint8_t currentValue = readCV(cvAddress);
1256  uint8_t newValueMask = 1 << (cvValue & 0b00000111);
1257  if(cvValue & 0b00001000)
1258  writeCV(cvAddress, currentValue | newValueMask);
1259  else
1260  writeCV(cvAddress, currentValue & ~newValueMask);
1261  }
1262  break;
1263  }
1264  }
1265  }
1266  }
1267 
1268 #ifdef NMRA_DCC_PROCESS_MULTIFUNCTION
1269  // Multi Function Decoders (14-bit address)
1270  else if( pDccMsg->Data[0] < 232 )
1271  {
1272  uint16_t Address ;
1273  Address = ( ( pDccMsg->Data[0] - 192 ) << 8 ) | pDccMsg->Data[1];
1274  //TODO should we convert Address to 1 .. 10239 ?
1275  processMultiFunctionMessage( Address, DCC_ADDR_LONG, pDccMsg->Data[2], pDccMsg->Data[3], pDccMsg->Data[4] ) ;
1276  }
1277 #endif
1278 #ifdef NMRA_DCC_PROCESS_SERVICEMODE
1279  }
1280 #endif
1281  }
1282 }
1283 
1285 NmraDcc::NmraDcc()
1286 {
1287 }
1288 
1289 #ifdef digitalPinToInterrupt
1290 void NmraDcc::pin( uint8_t ExtIntPinNum, uint8_t EnablePullup)
1291 {
1292  pin(digitalPinToInterrupt(ExtIntPinNum), ExtIntPinNum, EnablePullup);
1293 }
1294 #endif
1295 
1296 void NmraDcc::pin( uint8_t ExtIntNum, uint8_t ExtIntPinNum, uint8_t EnablePullup)
1297 {
1298 #if defined ( __STM32F1__ )
1299  // with STM32F1 the interuptnumber is equal the pin number
1300  DccProcState.ExtIntNum = ExtIntPinNum;
1301 #else
1302  DccProcState.ExtIntNum = ExtIntNum;
1303 #endif
1304  DccProcState.ExtIntPinNum = ExtIntPinNum;
1305 
1306  pinMode( ExtIntPinNum, INPUT );
1307  if( EnablePullup )
1308  digitalWrite(ExtIntPinNum, HIGH);
1309 }
1310 
1312 void NmraDcc::initAccessoryDecoder( uint8_t ManufacturerId, uint8_t VersionId, uint8_t Flags, uint8_t OpsModeAddressBaseCV )
1313 {
1314  init(ManufacturerId, VersionId, Flags | FLAGS_DCC_ACCESSORY_DECODER, OpsModeAddressBaseCV);
1315 }
1316 
1318 void NmraDcc::init( uint8_t ManufacturerId, uint8_t VersionId, uint8_t Flags, uint8_t OpsModeAddressBaseCV )
1319 {
1320  #if defined(ESP8266)
1321  EEPROM.begin(MAXCV);
1322  #endif
1323  #if defined(ESP32)
1324  EEPROM.begin(MAXCV);
1325  #endif
1326  // Clear all the static member variables
1327  memset( &DccRx, 0, sizeof( DccRx) );
1328 
1329  MODE_TP1; // only for debugging and timing measurement
1330  MODE_TP2;
1331  MODE_TP3;
1332  MODE_TP4;
1333  ISREdge = RISING;
1334  bitMax = MAX_ONEBITFULL;
1335  bitMin = MIN_ONEBITFULL;
1336  attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, RISING);
1337 
1338  DccProcState.Flags = Flags ;
1339  DccProcState.OpsModeAddressBaseCV = OpsModeAddressBaseCV ;
1340  DccProcState.myDccAddress = -1;
1341  DccProcState.inAccDecDCCAddrNextReceivedMode = 0;
1342 
1343  // Set the Bits that control Multifunction or Accessory behaviour
1344  // and if the Accessory decoder optionally handles Output Addressing
1345  // we need to peal off the top two bits
1346  writeCV( CV_29_CONFIG, ( readCV( CV_29_CONFIG ) & ~FLAGS_CV29_BITS ) | (Flags & FLAGS_CV29_BITS) ) ;
1347 
1348  uint8_t doAutoFactoryDefault = 0;
1349  if((Flags & FLAGS_AUTO_FACTORY_DEFAULT) && (readCV(CV_VERSION_ID) == 255) && (readCV(CV_MANUFACTURER_ID) == 255))
1350  doAutoFactoryDefault = 1;
1351 
1352  writeCV( CV_VERSION_ID, VersionId ) ;
1353  writeCV( CV_MANUFACTURER_ID, ManufacturerId ) ;
1354 
1355  clearDccProcState( 0 );
1356 
1357  if(notifyCVResetFactoryDefault && doAutoFactoryDefault)
1358  notifyCVResetFactoryDefault();
1359 }
1360 
1362 uint8_t NmraDcc::getCV( uint16_t CV )
1363 {
1364  return readCV(CV);
1365 }
1366 
1368 uint8_t NmraDcc::setCV( uint16_t CV, uint8_t Value)
1369 {
1370  DccProcState.Flags |= FLAGS_SETCV_CALLED;
1371 
1372  uint8_t returnValue = writeCV(CV,Value);
1373 
1374  DccProcState.Flags &= ~~FLAGS_SETCV_CALLED;
1375 
1376  return returnValue;
1377 }
1378 
1380 uint16_t NmraDcc::getAddr(void)
1381 {
1382  return getMyAddr();
1383 }
1384 
1386 uint8_t NmraDcc::isSetCVReady(void)
1387 {
1388  if(notifyIsSetCVReady)
1389  return notifyIsSetCVReady();
1390  return readyEEPROM();
1391 }
1392 
1394 #ifdef DCC_DEBUG
1395 uint8_t NmraDcc::getIntCount(void)
1396 {
1397  return DccProcState.IntCount;
1398 }
1399 
1401 uint8_t NmraDcc::getTickCount(void)
1402 {
1403  return DccProcState.TickCount;
1404 }
1405 
1407 uint8_t NmraDcc::getNestedIrqCount(void)
1408 {
1409  return DccProcState.NestedIrqCount;
1410 }
1411 
1413 uint8_t NmraDcc::getState(void)
1414 {
1415  return DccRx.State;
1416 }
1417 
1419 uint8_t NmraDcc::getBitCount(void)
1420 {
1421  return DccRx.BitCount;
1422 }
1423 #endif
1424 
1426 void NmraDcc::setAccDecDCCAddrNextReceived(uint8_t enable)
1427 {
1428  DccProcState.inAccDecDCCAddrNextReceivedMode = enable;
1429 }
1430 
1432 uint8_t NmraDcc::process()
1433 {
1434  if( DccProcState.inServiceMode )
1435  {
1436  if( (millis() - DccProcState.LastServiceModeMillis ) > 20L )
1437  {
1438  clearDccProcState( 0 ) ;
1439  }
1440  }
1441 
1442  if( DccRx.DataReady )
1443  {
1444  // We need to do this check with interrupts disabled
1445  //SET_TP4;
1446  noInterrupts();
1447  Msg = DccRx.PacketCopy ;
1448  DccRx.DataReady = 0 ;
1449  interrupts();
1450  #ifdef DCC_DBGVAR
1451  countOf.Tel++;
1452  #endif
1453 
1454  uint8_t xorValue = 0 ;
1455 
1456  for(uint8_t i = 0; i < DccRx.PacketCopy.Size; i++)
1457  xorValue ^= DccRx.PacketCopy.Data[i];
1458  if(xorValue) {
1459  #ifdef DCC_DBGVAR
1460  DB_PRINT("Cerr");
1461  countOf.Err++;
1462  #endif
1463  return 0 ;
1464  } else {
1465  if( notifyDccMsg ) notifyDccMsg( &Msg );
1466 
1467  execDccProcessor( &Msg );
1468  }
1469  return 1 ;
1470  }
1471 
1472  return 0 ;
1473 };
1474 #endif