39 #ifndef NO_DCCCOMMANDERNMRA 43 #include <avr/eeprom.h> 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 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) 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__)) 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__) 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); 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); 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 ); } 241 #define DB_PRINT( x, ... ) ; 242 #define DB_PRINT_( x, ... ) ; 246 struct countOf_t countOf;
249 #if defined ( __STM32F1__ ) 250 static ExtIntTriggerMode ISREdge;
254 static word bitMax, bitMin;
267 OPS_INS_RESERVED = 0,
269 OPS_INS_BIT_MANIPULATION,
276 DccRxWaitState State ;
288 uint8_t OpsModeAddressBaseCV ;
289 uint8_t inServiceMode ;
290 long LastServiceModeMillis ;
291 uint8_t PageRegister ;
292 uint8_t DuplicateCount ;
295 uint8_t ExtIntPinNum;
296 int16_t myDccAddress;
297 uint8_t inAccDecDCCAddrNextReceivedMode;
301 uint8_t NestedIrqCount;
308 void ExternalInterruptHandler(
void)
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 ) {
321 DccProcState.NestedIrqCount++;
327 actMicros = micros();
328 bitMicros = actMicros-lastMicros;
329 if ( bitMicros < bitMin ) {
335 DccBitVal = ( bitMicros < bitMax );
336 lastMicros = actMicros;
338 if(DccBitVal) {SET_TP2;}
else {CLR_TP2;};
340 DCC_IrqRunning =
true;
343 DccProcState.TickCount++;
346 switch( DccRx.State )
353 if( DccRx.BitCount > 10 ) {
354 DccRx.State = WAIT_START_BIT ;
357 #if defined ( __STM32F1__ ) 358 detachInterrupt( DccProcState.ExtIntNum );
360 attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, CHANGE);
362 bitMax = MAX_ONEBITHALF;
363 bitMin = MIN_ONEBITHALF;
395 if( abs(bit2-bit1) > MAX_BITDIFF ) {
399 DccRx.State = WAIT_PREAMBLE;
400 bitMax = MAX_PRAEAMBEL;
401 bitMin = MIN_ONEBITFULL;
404 #if defined ( __STM32F1__ ) 405 detachInterrupt( DccProcState.ExtIntNum );
407 attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge );
422 DccRx.State = WAIT_PREAMBLE;
423 bitMax = MAX_PRAEAMBEL;
424 bitMin = MIN_ONEBITFULL;
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;
438 DccRx.PacketBuf.PreambleBits = DccRx.BitCount;
443 #if defined ( __STM32F1__ ) 444 detachInterrupt( DccProcState.ExtIntNum );
446 attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge );
454 DccRx.State = WAIT_PREAMBLE;
455 bitMax = MAX_PRAEAMBEL;
456 bitMin = MIN_ONEBITFULL;
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;
468 DccRx.PacketBuf.PreambleBits = DccRx.BitCount;
475 #if defined ( __STM32F1__ ) 476 detachInterrupt( DccProcState.ExtIntNum );
478 attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge );
487 DccRx.TempByte = ( DccRx.TempByte << 1 ) ;
489 DccRx.TempByte |= 1 ;
491 if( DccRx.BitCount == 8 )
493 if( DccRx.PacketBuf.Size == MAX_DCC_MESSAGE_LEN )
495 DccRx.State = WAIT_PREAMBLE ;
496 bitMax = MAX_PRAEAMBEL;
497 bitMin = MIN_ONEBITFULL;
502 DccRx.State = WAIT_END_BIT ;
503 DccRx.PacketBuf.Data[ DccRx.PacketBuf.Size++ ] = DccRx.TempByte ;
513 DccRx.State = WAIT_PREAMBLE ;
514 bitMax = MAX_PRAEAMBEL;
515 bitMin = MIN_ONEBITFULL;
516 DccRx.PacketCopy = DccRx.PacketBuf ;
517 DccRx.DataReady = 1 ;
522 if( DccRx.PacketBuf.Size == MAX_DCC_MESSAGE_LEN )
524 DccRx.State = WAIT_PREAMBLE ;
525 bitMax = MAX_PRAEAMBEL;
526 bitMin = MIN_ONEBITFULL;
531 DccRx.State = WAIT_DATA ;
539 DCC_IrqRunning =
false;
548 uint8_t readEEPROM(
unsigned int CV ) {
549 return EEPROM.read(CV) ;
552 void writeEEPROM(
unsigned int CV, uint8_t Value ) {
553 EEPROM.write(CV, Value) ;
564 return eeprom_is_ready();
571 uint8_t validCV( uint16_t CV, uint8_t Writable )
573 if( notifyCVResetFactoryDefault && (CV == CV_MANUFACTURER_ID ) && Writable )
574 notifyCVResetFactoryDefault();
577 return notifyCVValid( CV, Writable ) ;
584 if( Writable && ( ( CV ==CV_VERSION_ID ) || (CV == CV_MANUFACTURER_ID ) ) )
590 uint8_t readCV(
unsigned int CV )
595 return notifyCVRead( CV ) ;
597 Value = readEEPROM(CV);
601 uint8_t writeCV(
unsigned int CV, uint8_t Value)
607 DccProcState.Flags = ( DccProcState.Flags & ~~FLAGS_CV29_BITS) | (Value & FLAGS_CV29_BITS);
609 case CV_ACCESSORY_DECODER_ADDRESS_LSB:
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;
617 return notifyCVWrite( CV, Value ) ;
619 if( readEEPROM( CV ) != Value )
621 writeEEPROM( CV, Value ) ;
624 notifyCVChange( CV, Value) ;
626 if( notifyDccCVChange && !(DccProcState.Flags & FLAGS_SETCV_CALLED) )
627 notifyDccCVChange( CV, Value );
630 return readEEPROM( CV ) ;
633 uint16_t getMyAddr(
void)
637 if( DccProcState.myDccAddress != -1 )
638 return( DccProcState.myDccAddress );
640 CV29Value = readCV( CV_29_CONFIG ) ;
642 if( CV29Value & CV29_ACCESSORY_DECODER )
644 if( CV29Value & CV29_OUTPUT_ADDRESS_MODE )
645 DccProcState.myDccAddress = ( readCV( CV_ACCESSORY_DECODER_ADDRESS_MSB ) << 8 ) | readCV( CV_ACCESSORY_DECODER_ADDRESS_LSB );
647 DccProcState.myDccAddress = ( ( readCV( CV_ACCESSORY_DECODER_ADDRESS_MSB ) & 0b00000111) << 6 ) | ( readCV( CV_ACCESSORY_DECODER_ADDRESS_LSB ) & 0b00111111) ;
651 if( CV29Value & CV29_EXT_ADDRESSING )
652 DccProcState.myDccAddress = ( ( readCV( CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB ) - 192 ) << 8 ) | readCV( CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB ) ;
655 DccProcState.myDccAddress = readCV( 1 ) ;
658 return DccProcState.myDccAddress ;
661 void processDirectOpsOperation( uint8_t Cmd, uint16_t CVAddr, uint8_t Value )
669 if( validCV( CVAddr, 1 ) )
671 if( writeCV( CVAddr, Value ) == Value )
678 if( validCV( CVAddr, 0 ) )
680 if( readCV( CVAddr ) == Value )
688 uint8_t BitMask = (1 << (Value & 0x07) ) ;
689 uint8_t BitValue = Value & 0x08 ;
690 uint8_t BitWrite = Value & 0x10 ;
692 uint8_t tempValue = readCV( CVAddr ) ;
697 if( validCV( CVAddr, 1 ) )
700 tempValue |= BitMask ;
703 tempValue &= ~~BitMask ;
705 if( writeCV( CVAddr, tempValue ) == tempValue )
713 if( validCV( CVAddr, 0 ) )
717 if( tempValue & BitMask )
722 if( !( tempValue & BitMask) )
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 )
737 DCC_SPEED_STEPS speedSteps ;
739 uint8_t CmdMasked = Cmd & 0b11100000 ;
742 if( DccProcState.Flags & FLAGS_DCC_ACCESSORY_DECODER )
746 if( ( CmdMasked != 0b11100000 ) || ( DccProcState.OpsModeAddressBaseCV == 0 ) )
749 uint16_t FakeOpsAddr = readCV( DccProcState.OpsModeAddressBaseCV ) | ( readCV( DccProcState.OpsModeAddressBaseCV + 1 ) << 8 ) ;
750 uint16_t OpsAddr = Addr & 0x3FFF ;
752 if( OpsAddr != FakeOpsAddr )
757 else if( ( DccProcState.Flags & FLAGS_MY_ADDRESS_ONLY ) && ( Addr != getMyAddr() ) && ( Addr != 0 ) )
763 switch( Cmd & 0b00001110 )
766 if( notifyDccReset && ( Cmd & 0b00000001 ) )
768 notifyDccReset( 1 ) ;
789 switch( Cmd & 0b00011111 )
794 switch( Data1 & 0b01111111 )
805 speed = (Data1 & 0b01111111) ;
807 dir = (DCC_DIRECTION) ((Data1 & 0b10000000) >> 7) ;
808 notifyDccSpeed( Addr, AddrType, speed, dir, SPEED_STEP_128 ) ;
816 #ifdef NMRA_DCC_ENABLE_14_SPEED_STEP_MODE 817 speedSteps = (readCV( CV_29_CONFIG ) & CV29_F0_LOCATION) ? SPEED_STEP_28 : SPEED_STEP_14 ;
819 speedSteps = SPEED_STEP_28 ;
823 switch( Cmd & 0b00011111 )
836 #ifdef NMRA_DCC_ENABLE_14_SPEED_STEP_MODE 837 if( speedSteps == SPEED_STEP_14 )
839 speed = (Cmd & 0b00001111) ;
844 speed = (((Cmd & 0b00001111) << 1 ) | ((Cmd & 0b00010000) >> 4)) - 2 ;
845 #ifdef NMRA_DCC_ENABLE_14_SPEED_STEP_MODE 849 dir = (DCC_DIRECTION) ((Cmd & 0b00100000) >> 5) ;
850 notifyDccSpeed( Addr, AddrType, speed, dir, speedSteps ) ;
852 if( notifyDccSpeedRaw )
853 notifyDccSpeedRaw(Addr, AddrType, Cmd );
855 #ifdef NMRA_DCC_ENABLE_14_SPEED_STEP_MODE 856 if( notifyDccFunc && (speedSteps == SPEED_STEP_14) )
859 uint8_t fn0 = (Cmd & 0b00010000) ;
860 notifyDccFunc( Addr, AddrType, FN_0, fn0 ) ;
869 notifyDccFunc( Addr, AddrType, FN_0_4, Cmd & 0b00011111 ) ;
876 if (Cmd & 0b00010000 )
877 notifyDccFunc( Addr, AddrType, FN_5_8, Cmd & 0b00001111 ) ;
879 notifyDccFunc( Addr, AddrType, FN_9_12, Cmd & 0b00001111 ) ;
884 switch(Cmd & 0b00011111)
888 notifyDccFunc( Addr, AddrType, FN_13_20, Data1 ) ;
893 notifyDccFunc( Addr, AddrType, FN_21_28, Data1 ) ;
899 CVAddr = ( ( ( Cmd & 0x03 ) << 8 ) | Data1 ) + 1 ;
901 processDirectOpsOperation( Cmd, CVAddr, Data2 ) ;
908 #ifdef NMRA_DCC_PROCESS_SERVICEMODE 909 void processServiceModeOperation(
DCC_MSG * pDccMsg )
913 if( pDccMsg->Size == 3)
915 uint8_t RegisterAddr ;
916 DB_PRINT(
"3-BytePkt");
917 RegisterAddr = pDccMsg->Data[0] & 0x07 ;
918 Value = pDccMsg->Data[1] ;
920 if( RegisterAddr == 5 )
922 DccProcState.PageRegister = Value ;
928 if( RegisterAddr == 4 )
929 CVAddr = CV_29_CONFIG ;
931 else if( ( RegisterAddr <= 3 ) && ( DccProcState.PageRegister > 0 ) )
932 CVAddr = ( ( DccProcState.PageRegister - 1 ) * 4 ) + RegisterAddr + 1 ;
935 CVAddr = RegisterAddr + 1 ;
937 if( pDccMsg->Data[0] & 0x08 )
939 if( validCV( CVAddr, 1 ) )
941 if( writeCV( CVAddr, Value ) == Value )
948 if( validCV( CVAddr, 0 ) )
950 if( readCV( CVAddr ) == Value )
957 else if( pDccMsg->Size == 4)
960 CVAddr = ( ( ( pDccMsg->Data[0] & 0x03 ) << 8 ) | pDccMsg->Data[1] ) + 1 ;
961 Value = pDccMsg->Data[2] ;
963 processDirectOpsOperation( pDccMsg->Data[0] & 0b00001100, CVAddr, Value ) ;
969 void resetServiceModeTimer(uint8_t inServiceMode)
971 if (notifyServiceMode && inServiceMode != DccProcState.inServiceMode)
973 notifyServiceMode(inServiceMode);
976 DccProcState.inServiceMode = inServiceMode ;
978 DccProcState.LastServiceModeMillis = inServiceMode ? millis() : 0 ;
979 if (notifyServiceMode && inServiceMode != DccProcState.inServiceMode)
981 notifyServiceMode(inServiceMode);
986 void clearDccProcState(uint8_t inServiceMode)
988 resetServiceModeTimer( inServiceMode ) ;
991 DccProcState.PageRegister = 1 ;
994 DccProcState.DuplicateCount = 0 ;
995 memset( &DccProcState.LastMsg, 0,
sizeof(
DCC_MSG ) ) ;
1000 void SerialPrintPacketHex(
const __FlashStringHelper *strLabel,
DCC_MSG * pDccMsg)
1002 Serial.print( strLabel );
1004 for( uint8_t i = 0; i < pDccMsg->Size; i++ )
1006 if( pDccMsg->Data[i] <= 9)
1009 Serial.print( pDccMsg->Data[i], HEX );
1010 Serial.write(
' ' );
1017 void execDccProcessor(
DCC_MSG * pDccMsg )
1019 if( ( pDccMsg->Data[0] == 0 ) && ( pDccMsg->Data[1] == 0 ) )
1021 if( notifyDccReset )
1022 notifyDccReset( 0 ) ;
1024 #ifdef NMRA_DCC_PROCESS_SERVICEMODE 1026 if( DccProcState.inServiceMode )
1027 resetServiceModeTimer( 1 ) ;
1029 clearDccProcState( 1 );
1035 #ifdef NMRA_DCC_PROCESS_SERVICEMODE 1036 if( DccProcState.inServiceMode && ( pDccMsg->Data[0] >= 112 ) && ( pDccMsg->Data[0] < 128 ) )
1038 resetServiceModeTimer( 1 ) ;
1040 if( memcmp( pDccMsg, &DccProcState.LastMsg,
sizeof(
DCC_MSG ) ) )
1042 DccProcState.DuplicateCount = 0 ;
1043 memcpy( &DccProcState.LastMsg, pDccMsg,
sizeof(
DCC_MSG ) ) ;
1048 DccProcState.DuplicateCount++ ;
1049 processServiceModeOperation( pDccMsg ) ;
1055 if( DccProcState.inServiceMode )
1056 clearDccProcState( 0 );
1060 if( ( pDccMsg->Data[0] == 0b11111111 ) && ( pDccMsg->Data[1] == 0 ) )
1066 #ifdef NMRA_DCC_PROCESS_MULTIFUNCTION 1068 else if( pDccMsg->Data[0] < 128 )
1069 processMultiFunctionMessage( pDccMsg->Data[0], DCC_ADDR_SHORT, pDccMsg->Data[1], pDccMsg->Data[2], pDccMsg->Data[3] ) ;
1072 else if( pDccMsg->Data[0] < 192 )
1074 else if( ( pDccMsg->Data[0] >= 128 ) && ( pDccMsg->Data[0] < 192 ) )
1077 if( DccProcState.Flags & FLAGS_DCC_ACCESSORY_DECODER )
1079 int16_t BoardAddress ;
1080 int16_t OutputAddress ;
1081 uint8_t TurnoutPairIndex ;
1084 SerialPrintPacketHex(F(
"eDP: AccCmd: "), pDccMsg);
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);
1093 if((pDccMsg->Size == 5) && ((pDccMsg->Data[1] & 0b10001100) == 0b00001100))
1095 DB_PRINT(
"eDP: Legacy Accessory Decoder CV Access Command");
1097 if((BoardAddress != getMyAddr()) && ( BoardAddress < 511 ))
1099 DB_PRINT(
"eDP: Board Address Not Matched");
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);
1112 OutputAddress = (((BoardAddress - 1) << 2 ) | TurnoutPairIndex) + 1 ;
1114 DB_PRINT(
"eDP: OAddr:%d", OutputAddress);
1116 if( DccProcState.inAccDecDCCAddrNextReceivedMode)
1118 if( DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE )
1120 DB_PRINT(
"eDP: Set OAddr:%d", OutputAddress);
1122 writeCV(CV_ACCESSORY_DECODER_ADDRESS_LSB, (uint8_t)(OutputAddress % 256));
1123 writeCV(CV_ACCESSORY_DECODER_ADDRESS_MSB, (uint8_t)(OutputAddress / 256));
1125 if( notifyDccAccOutputAddrSet )
1126 notifyDccAccOutputAddrSet(OutputAddress);
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));
1134 if( notifyDccAccBoardAddrSet )
1135 notifyDccAccBoardAddrSet(BoardAddress);
1138 DccProcState.inAccDecDCCAddrNextReceivedMode = 0;
1142 if( DccProcState.Flags & FLAGS_MY_ADDRESS_ONLY )
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() );
1151 if( ( BoardAddress != getMyAddr() ) && ( BoardAddress < 511 ) ) {
1152 DB_PRINT(
" eDP: BAddr:%d, myAddr:%d - no match", BoardAddress, getMyAddr() );
1156 DB_PRINT(
"eDP: Address Matched");
1160 if((pDccMsg->Size == 4) && ((pDccMsg->Data[1] & 0b10001001) == 1))
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);
1170 if( notifyDccSigState )
1171 notifyDccSigState( OutputAddress, TurnoutPairIndex, pDccMsg->Data[2] ) ;
1174 else if(pDccMsg->Size == 3)
1176 uint8_t direction = pDccMsg->Data[1] & 0b00000001;
1177 uint8_t outputPower = (pDccMsg->Data[1] & 0b00001000) >> 3;
1180 if ( notifyDccAccState )
1181 notifyDccAccState( OutputAddress, BoardAddress, pDccMsg->Data[1] & 0b00000111, outputPower );
1183 if( DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE )
1185 DB_PRINT(
"eDP: OAddr:%d Turnout Dir:%d Output Power:%d", OutputAddress, direction, outputPower);
1186 if( notifyDccAccTurnoutOutput )
1187 notifyDccAccTurnoutOutput( OutputAddress, direction, outputPower );
1191 DB_PRINT(
"eDP: Turnout Pair Index:%d Dir:%d Output Power: ", TurnoutPairIndex, direction, outputPower);
1192 if( notifyDccAccTurnoutBoard )
1193 notifyDccAccTurnoutBoard( BoardAddress, TurnoutPairIndex, direction, outputPower );
1196 else if(pDccMsg->Size == 6)
1198 DB_PRINT(
"eDP: OPS Mode CV Programming Command");
1200 if(((pDccMsg->Data[1] & 0b10001001) != 1) && ((pDccMsg->Data[1] & 0b10001111) != 0x80))
1202 DB_PRINT(
"eDP: Unsupported OPS Mode CV Addressing Mode");
1207 if(DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE)
1209 DB_PRINT(
"eDP: Check Output Address:%d", OutputAddress);
1210 if((OutputAddress != getMyAddr()) && ( OutputAddress < 2045 ))
1212 DB_PRINT(
"eDP: Output Address Not Matched");
1218 DB_PRINT(
"eDP: Check Board Address:%d", BoardAddress);
1219 if((BoardAddress != getMyAddr()) && ( BoardAddress < 511 ))
1221 DB_PRINT(
"eDP: Board Address Not Matched");
1226 uint16_t cvAddress = ((pDccMsg->Data[2] & 0b00000011) << 8) + pDccMsg->Data[3] + 1;
1227 uint8_t cvValue = pDccMsg->Data[4];
1229 OpsInstructionType insType = (OpsInstructionType)((pDccMsg->Data[2] & 0b00001100) >> 2) ;
1231 DB_PRINT(
"eDP: OPS Mode Instruction:%d", insType);
1234 case OPS_INS_RESERVED:
1235 case OPS_INS_VERIFY_BYTE:
1236 DB_PRINT(
"eDP: Unsupported OPS Mode Instruction:%d", insType);
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);
1251 case OPS_INS_BIT_MANIPULATION:
1253 if((cvValue & 0b00010000) && validCV(cvAddress, 1 ))
1255 uint8_t currentValue = readCV(cvAddress);
1256 uint8_t newValueMask = 1 << (cvValue & 0b00000111);
1257 if(cvValue & 0b00001000)
1258 writeCV(cvAddress, currentValue | newValueMask);
1260 writeCV(cvAddress, currentValue & ~newValueMask);
1268 #ifdef NMRA_DCC_PROCESS_MULTIFUNCTION 1270 else if( pDccMsg->Data[0] < 232 )
1273 Address = ( ( pDccMsg->Data[0] - 192 ) << 8 ) | pDccMsg->Data[1];
1275 processMultiFunctionMessage( Address, DCC_ADDR_LONG, pDccMsg->Data[2], pDccMsg->Data[3], pDccMsg->Data[4] ) ;
1278 #ifdef NMRA_DCC_PROCESS_SERVICEMODE 1289 #ifdef digitalPinToInterrupt 1290 void NmraDcc::pin( uint8_t ExtIntPinNum, uint8_t EnablePullup)
1292 pin(digitalPinToInterrupt(ExtIntPinNum), ExtIntPinNum, EnablePullup);
1296 void NmraDcc::pin( uint8_t ExtIntNum, uint8_t ExtIntPinNum, uint8_t EnablePullup)
1298 #if defined ( __STM32F1__ ) 1300 DccProcState.ExtIntNum = ExtIntPinNum;
1302 DccProcState.ExtIntNum = ExtIntNum;
1304 DccProcState.ExtIntPinNum = ExtIntPinNum;
1306 pinMode( ExtIntPinNum, INPUT );
1308 digitalWrite(ExtIntPinNum, HIGH);
1312 void NmraDcc::initAccessoryDecoder( uint8_t ManufacturerId, uint8_t VersionId, uint8_t Flags, uint8_t OpsModeAddressBaseCV )
1314 init(ManufacturerId, VersionId, Flags | FLAGS_DCC_ACCESSORY_DECODER, OpsModeAddressBaseCV);
1318 void NmraDcc::init( uint8_t ManufacturerId, uint8_t VersionId, uint8_t Flags, uint8_t OpsModeAddressBaseCV )
1320 #if defined(ESP8266) 1321 EEPROM.begin(MAXCV);
1324 EEPROM.begin(MAXCV);
1327 memset( &DccRx, 0,
sizeof( DccRx) );
1334 bitMax = MAX_ONEBITFULL;
1335 bitMin = MIN_ONEBITFULL;
1336 attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, RISING);
1338 DccProcState.Flags = Flags ;
1339 DccProcState.OpsModeAddressBaseCV = OpsModeAddressBaseCV ;
1340 DccProcState.myDccAddress = -1;
1341 DccProcState.inAccDecDCCAddrNextReceivedMode = 0;
1346 writeCV( CV_29_CONFIG, ( readCV( CV_29_CONFIG ) & ~FLAGS_CV29_BITS ) | (Flags & FLAGS_CV29_BITS) ) ;
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;
1352 writeCV( CV_VERSION_ID, VersionId ) ;
1353 writeCV( CV_MANUFACTURER_ID, ManufacturerId ) ;
1355 clearDccProcState( 0 );
1357 if(notifyCVResetFactoryDefault && doAutoFactoryDefault)
1358 notifyCVResetFactoryDefault();
1362 uint8_t NmraDcc::getCV( uint16_t CV )
1368 uint8_t NmraDcc::setCV( uint16_t CV, uint8_t Value)
1370 DccProcState.Flags |= FLAGS_SETCV_CALLED;
1372 uint8_t returnValue = writeCV(CV,Value);
1374 DccProcState.Flags &= ~~FLAGS_SETCV_CALLED;
1380 uint16_t NmraDcc::getAddr(
void)
1386 uint8_t NmraDcc::isSetCVReady(
void)
1388 if(notifyIsSetCVReady)
1389 return notifyIsSetCVReady();
1390 return readyEEPROM();
1395 uint8_t NmraDcc::getIntCount(
void)
1397 return DccProcState.IntCount;
1401 uint8_t NmraDcc::getTickCount(
void)
1403 return DccProcState.TickCount;
1407 uint8_t NmraDcc::getNestedIrqCount(
void)
1409 return DccProcState.NestedIrqCount;
1413 uint8_t NmraDcc::getState(
void)
1419 uint8_t NmraDcc::getBitCount(
void)
1421 return DccRx.BitCount;
1426 void NmraDcc::setAccDecDCCAddrNextReceived(uint8_t enable)
1428 DccProcState.inAccDecDCCAddrNextReceivedMode = enable;
1432 uint8_t NmraDcc::process()
1434 if( DccProcState.inServiceMode )
1436 if( (millis() - DccProcState.LastServiceModeMillis ) > 20L )
1438 clearDccProcState( 0 ) ;
1442 if( DccRx.DataReady )
1447 Msg = DccRx.PacketCopy ;
1448 DccRx.DataReady = 0 ;
1454 uint8_t xorValue = 0 ;
1456 for(uint8_t i = 0; i < DccRx.PacketCopy.Size; i++)
1457 xorValue ^= DccRx.PacketCopy.Data[i];
1465 if( notifyDccMsg ) notifyDccMsg( &Msg );
1467 execDccProcessor( &Msg );