14 Commits

Author SHA1 Message Date
Alex Shepherd
6a7e206032 reverted changes around lastMicros 2019-08-05 21:30:39 +12:00
Alex Shepherd
6d12e6cd3f added conditional compilation for ESP8266 to add ICACHE_RAM_ATTR to ExternalInterruptHandler
changed storage for Micros to unsigned long
2019-05-25 15:52:55 +12:00
Alex Shepherd
b249762550 changed the version to 201 in the header 2019-05-02 21:42:59 +12:00
Alex Shepherd
5cee0d28ed Merge branch 'master' into ESP32-IRAM_ATTR 2019-05-02 19:11:05 +12:00
Alex Shepherd
5ba1ee3e8e added another example of s simple DCC Multifunction (Locomotive) decoder 2019-05-02 11:13:22 +12:00
Franz-Peter
bb2a659ebe Esp32 processor specific (#23)
* outputaddressing corrected

declared notifyDccAccState for backward compatibility

* version define in NmraDcc.h

* DB_PRINT introduced

Changed debug printing to a macro.
Added cv29 to CV-addresses that reset caching of myAddress

* Corrections regarding Outputaddressing

OutputAddress must be a signed variable

* Changes/additions regarding output addressing and CVChange callback
Change Flag FLAGS_OUTPUT_ADDRESS_MODE accordingly, when CV29 Bit 6 (output addressing) is changed.
New callback 'notifyDccCVChange' which is NOT called if the CV is changed by means of the setCV() method

* Shorten Debug Messages

Because of Buffer overrun in the serial output. This leads to blocking
Serial.write() calls

* notifyDccSigState restored

Restore the old callback notifyDccSigState for compatibiltity to version
1.4.2

* switch off debug printing

* ESP32 specific changes

insert ESP32 specific changes reagarding the ISR by Hans Tanner
2019-02-22 08:42:34 +13:00
Alex Shepherd
865d919802 Added IRAM_ATTR changes for the ESP32 from Hans Tanner
bumped version to 2.0.1
2019-02-16 22:09:19 +13:00
Thierry Paris
ff3e24dff4 Add ESP32 support (#21)
* Update README.md

* Added ESP32 support.
2019-01-23 14:15:46 +13:00
Geoff Bunza
6dca23bc27 Gbsma601 (#20)
* Delete AccDec_7ServoBackandForth6Ftn.ino

* Delete AccDec_10Servos_7LED_6Ftn.ino

* Delete AccDec_13Servos_4LED_6Ftn.ino

* Delete AccDec_15Servos_2LED_6Ftn.ino

* Delete AccDec_17LED_1Ftn.ino

* Delete AccDec_17LED_6Ftn.ino

* Delete AccDec_7Servos_10LED_6Ftn.ino

* Delete Dec_10Serv_7LED_6Ftn.ino

* Delete Dec_13Serv_4LED_6Ftn.ino

* Delete Dec_15Serv_2LED_6Ftn.ino

* Delete Dec_17LED_1Ftn.ino

* Delete Dec_17LED_6Ftn.ino

* Delete Dec_2Mot_12LED_1Srv_6Ftn.ino

* Delete Dec_2Mot_3LED_TrigAud.ino

* Delete Dec_2Mot_4LED_Aud_8Ftn.ino

* Delete Dec_7Serv_10LED_6Ftn.ino

* Delete Dec_Dir_and_Fade.ino

* Delete Dec_SMA12_LED_Groups.ino

* Delete Dec_Stepper_6Ftn.ino

* Delete SMA 6.0 Release Notes.rtf

* Add files via upload

* Delete Dec_2Mot_12LED_1Srv_6Ftn.ino

* Delete Dec_2Mot_3LED_TrigAud.ino

* Delete Dec_2Mot_4LED_Aud_8Ftn.ino

* Add files via upload

* Delete SMA 6.01 Release Notes.rtf

* Add files via upload
2018-08-08 09:55:33 +12:00
per1234
15da83c411 Use a single tab field separator in keywords.txt (#19)
Each field of keywords.txt is separated by a single true tab. When you use multiple tabs it causes the field to be interpreted as empty. On Arduino IDE 1.6.5 and newer an empty KEYWORD_TOKENTYPE causes the default editor.function.style coloration to be used (as with KEYWORD2, KEYWORD3, LITERAL2). On Arduino IDE 1.6.4 and older it causes the keyword to not be recognized for any special coloration.

Reference:
https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords
2018-07-15 23:21:17 +12:00
Alex Shepherd
7a3845cbdf Changed the architectures to now be * as we're no longer tied to AVR specific hardware, however I've listed the architectures its been tested on
Fixed a bug with CV bit-write
2018-07-08 00:54:21 +12:00
Alex Shepherd
1717a2efb0 Made some minor tweaks / tidy-ups after committing Franz-Peter's changes 2018-07-07 19:21:48 +12:00
Franz-Peter
32c5597870 Additional changes regarding output addressing and new callback notifyDccCVChanged() (#17)
* outputaddressing corrected

declared notifyDccAccState for backward compatibility

* version define in NmraDcc.h

* DB_PRINT introduced

Changed debug printing to a macro.
Added cv29 to CV-addresses that reset caching of myAddress

* Corrections regarding Outputaddressing

OutputAddress must be a signed variable

* Changes/additions regarding output addressing and CVChange callback
Change Flag FLAGS_OUTPUT_ADDRESS_MODE accordingly, when CV29 Bit 6 (output addressing) is changed.
New callback 'notifyDccCVChange' which is NOT called if the CV is changed by means of the setCV() method

* Shorten Debug Messages

Because of Buffer overrun in the serial output. This leads to blocking
Serial.write() calls

* notifyDccSigState restored

Restore the old callback notifyDccSigState for compatibiltity to version
1.4.2

* switch off debug printing
2018-07-07 13:26:51 +12:00
Geoff Bunza
2de91bd4fd Merge pull request #18 from mrrwa/GB_SMAV6.0_Update&Test
Gb smav6.0 update&test
2018-07-05 16:38:11 -07:00
25 changed files with 2248 additions and 1651 deletions

View File

@@ -25,6 +25,8 @@
// 2017-01-19 added STM32F1 support by Franz-Peter // 2017-01-19 added STM32F1 support by Franz-Peter
// 2017-11-29 Ken West (kgw4449@gmail.com): // 2017-11-29 Ken West (kgw4449@gmail.com):
// Minor fixes to pass NMRA Baseline Conformance Tests. // 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
// //
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// //
@@ -39,7 +41,7 @@
#endif #endif
// Uncomment to print DEBUG messages // Uncomment to print DEBUG messages
// #define DEBUG_PRINT //#define DEBUG_PRINT
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// DCC Receive Routine // DCC Receive Routine
@@ -174,9 +176,22 @@
#define MODE_TP3 pinMode( D7,OUTPUT ) ; // GPIO 13 #define MODE_TP3 pinMode( D7,OUTPUT ) ; // GPIO 13
#define SET_TP3 GPOS = (1 << D7); #define SET_TP3 GPOS = (1 << D7);
#define CLR_TP3 GPOC = (1 << D7); #define CLR_TP3 GPOC = (1 << D7);
#define MODE_TP4 pinMode( D7,OUTPUT ); // GPIO 15 #define MODE_TP4 pinMode( D8,OUTPUT ) ; // GPIO 15
#define SET_TP4 GPOC = (1 << D8); #define SET_TP4 GPOC = (1 << D8);
#define CLR_TP4 GPOC = (1 << D8); #define CLR_TP4 GPOC = (1 << D8);
#elif defined(ESP32)
#define MODE_TP1 pinMode( 33,OUTPUT ) ; // GPIO 33
#define SET_TP1 GPOS = (1 << 33);
#define CLR_TP1 GPOC = (1 << 33);
#define MODE_TP2 pinMode( 25,OUTPUT ) ; // GPIO 25
#define SET_TP2 GPOS = (1 << 25);
#define CLR_TP2 GPOC = (1 << 25);
#define MODE_TP3 pinMode( 26,OUTPUT ) ; // GPIO 26
#define SET_TP3 GPOS = (1 << 26);
#define CLR_TP3 GPOC = (1 << 26);
#define MODE_TP4 pinMode( 27,OUTPUT ) ; // GPIO 27
#define SET_TP4 GPOC = (1 << 27);
#define CLR_TP4 GPOC = (1 << 27);
//#elif defined(__AVR_ATmega128__) ||defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__) //#elif defined(__AVR_ATmega128__) ||defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
@@ -230,8 +245,12 @@ struct countOf_t countOf;
#if defined ( __STM32F1__ ) #if defined ( __STM32F1__ )
static ExtIntTriggerMode ISREdge; 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 #else
static byte ISREdge; // RISING or FALLING static byte ISREdge; // Holder of the Next Edge we're looking for: RISING or FALLING
static byte ISRWatch; // Interrupt Handler Edge Filter
#endif #endif
static word bitMax, bitMin; static word bitMax, bitMin;
@@ -287,12 +306,43 @@ DCC_PROCESSOR_STATE ;
DCC_PROCESSOR_STATE DccProcState ; DCC_PROCESSOR_STATE DccProcState ;
#ifdef ESP32
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
void IRAM_ATTR ExternalInterruptHandler(void)
#elif defined(ESP8266)
void ICACHE_RAM_ATTR ExternalInterruptHandler(void)
#else
void ExternalInterruptHandler(void) 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 ------------------------------ // Bit evaluation without Timer 0 ------------------------------
uint8_t DccBitVal; uint8_t DccBitVal;
static int8_t bit1, bit2 ; static int8_t bit1, bit2 ;
static word lastMicros; static word lastMicros = 0;
static byte halfBit, DCC_IrqRunning; static byte halfBit, DCC_IrqRunning;
unsigned int actMicros, bitMicros; unsigned int actMicros, bitMicros;
if ( DCC_IrqRunning ) { if ( DCC_IrqRunning ) {
@@ -336,10 +386,15 @@ void ExternalInterruptHandler(void)
DccRx.State = WAIT_START_BIT ; DccRx.State = WAIT_START_BIT ;
// While waiting for the start bit, detect halfbit lengths. We will detect the correct // While waiting for the start bit, detect halfbit lengths. We will detect the correct
// sync and detect whether we see a false (e.g. motorola) protocol // sync and detect whether we see a false (e.g. motorola) protocol
#if defined ( __STM32F1__ ) #if defined ( __STM32F1__ )
detachInterrupt( DccProcState.ExtIntNum ); detachInterrupt( DccProcState.ExtIntNum );
#endif #endif
#ifdef ESP32
ISRWatch = CHANGE;
#else
attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, CHANGE); attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, CHANGE);
#endif
halfBit = 0; halfBit = 0;
bitMax = MAX_ONEBITHALF; bitMax = MAX_ONEBITHALF;
bitMin = MIN_ONEBITHALF; bitMin = MIN_ONEBITHALF;
@@ -383,10 +438,15 @@ void ExternalInterruptHandler(void)
bitMin = MIN_ONEBITFULL; bitMin = MIN_ONEBITFULL;
DccRx.BitCount = 0; DccRx.BitCount = 0;
SET_TP4; SET_TP4;
#if defined ( __STM32F1__ ) #if defined ( __STM32F1__ )
detachInterrupt( DccProcState.ExtIntNum ); detachInterrupt( DccProcState.ExtIntNum );
#endif #endif
#ifdef ESP32
ISRWatch = ISREdge;
#else
attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge ); attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge );
#endif
SET_TP3; SET_TP3;
CLR_TP4; CLR_TP4;
} }
@@ -422,10 +482,15 @@ void ExternalInterruptHandler(void)
DccRx.TempByte = 0 ; DccRx.TempByte = 0 ;
} }
SET_TP4; SET_TP4;
#if defined ( __STM32F1__ ) #if defined ( __STM32F1__ )
detachInterrupt( DccProcState.ExtIntNum ); detachInterrupt( DccProcState.ExtIntNum );
#endif #endif
#ifdef ESP32
ISRWatch = ISREdge;
#else
attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge ); attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge );
#endif
CLR_TP1; CLR_TP1;
CLR_TP4; CLR_TP4;
break; break;
@@ -454,10 +519,16 @@ void ExternalInterruptHandler(void)
CLR_TP1; CLR_TP1;
SET_TP4; SET_TP4;
#if defined ( __STM32F1__ ) #if defined ( __STM32F1__ )
detachInterrupt( DccProcState.ExtIntNum ); detachInterrupt( DccProcState.ExtIntNum );
#endif #endif
#ifdef ESP32
ISRWatch = ISREdge;
#else
attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge ); attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge );
#endif
CLR_TP4; CLR_TP4;
break; break;
@@ -495,8 +566,14 @@ void ExternalInterruptHandler(void)
DccRx.State = WAIT_PREAMBLE ; DccRx.State = WAIT_PREAMBLE ;
bitMax = MAX_PRAEAMBEL; bitMax = MAX_PRAEAMBEL;
bitMin = MIN_ONEBITFULL; bitMin = MIN_ONEBITFULL;
#ifdef ESP32
portENTER_CRITICAL_ISR(&mux);
#endif
DccRx.PacketCopy = DccRx.PacketBuf ; DccRx.PacketCopy = DccRx.PacketBuf ;
DccRx.DataReady = 1 ; DccRx.DataReady = 1 ;
#ifdef ESP32
portEXIT_CRITICAL_ISR(&mux);
#endif
SET_TP3; SET_TP3;
} }
else // Get next Byte else // Get next Byte
@@ -536,6 +613,9 @@ void writeEEPROM( unsigned int CV, uint8_t Value ) {
#if defined(ESP8266) #if defined(ESP8266)
EEPROM.commit(); EEPROM.commit();
#endif #endif
#if defined(ESP32)
EEPROM.commit();
#endif
} }
bool readyEEPROM() { bool readyEEPROM() {
@@ -581,11 +661,14 @@ uint8_t writeCV( unsigned int CV, uint8_t Value)
{ {
switch( CV ) switch( CV )
{ {
case CV_29_CONFIG:
// copy addressmode Bit to Flags
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 case CV_ACCESSORY_DECODER_ADDRESS_LSB: // Also same CV for CV_MULTIFUNCTION_PRIMARY_ADDRESS
case CV_ACCESSORY_DECODER_ADDRESS_MSB: case CV_ACCESSORY_DECODER_ADDRESS_MSB:
case CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB: case CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB:
case CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB: case CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB:
case CV_29_CONFIG:
DccProcState.myDccAddress = -1; // Assume any CV Write Operation might change the Address DccProcState.myDccAddress = -1; // Assume any CV Write Operation might change the Address
} }
@@ -598,7 +681,11 @@ uint8_t writeCV( unsigned int CV, uint8_t Value)
if( notifyCVChange ) if( notifyCVChange )
notifyCVChange( CV, Value) ; notifyCVChange( CV, Value) ;
if( notifyDccCVChange && !(DccProcState.Flags & FLAGS_SETCV_CALLED) )
notifyDccCVChange( CV, Value );
} }
return readEEPROM( CV ) ; return readEEPROM( CV ) ;
} }
@@ -882,11 +969,10 @@ void processServiceModeOperation( DCC_MSG * pDccMsg )
{ {
uint16_t CVAddr ; uint16_t CVAddr ;
uint8_t Value ; uint8_t Value ;
if( pDccMsg->Size == 3) // 3 Byte Packets are for Address Only, Register and Paged Mode if( pDccMsg->Size == 3) // 3 Byte Packets are for Address Only, Register and Paged Mode
{ {
uint8_t RegisterAddr ; uint8_t RegisterAddr ;
DB_PRINT("3-BytePkt");
RegisterAddr = pDccMsg->Data[0] & 0x07 ; RegisterAddr = pDccMsg->Data[0] & 0x07 ;
Value = pDccMsg->Data[1] ; Value = pDccMsg->Data[1] ;
@@ -929,6 +1015,7 @@ void processServiceModeOperation( DCC_MSG * pDccMsg )
else if( pDccMsg->Size == 4) // 4 Byte Packets are for Direct Byte & Bit Mode else if( pDccMsg->Size == 4) // 4 Byte Packets are for Direct Byte & Bit Mode
{ {
DB_PRINT("BB-Mode");
CVAddr = ( ( ( pDccMsg->Data[0] & 0x03 ) << 8 ) | pDccMsg->Data[1] ) + 1 ; CVAddr = ( ( ( pDccMsg->Data[0] & 0x03 ) << 8 ) | pDccMsg->Data[1] ) + 1 ;
Value = pDccMsg->Data[2] ; Value = pDccMsg->Data[2] ;
@@ -1048,46 +1135,48 @@ void execDccProcessor( DCC_MSG * pDccMsg )
{ {
if( DccProcState.Flags & FLAGS_DCC_ACCESSORY_DECODER ) if( DccProcState.Flags & FLAGS_DCC_ACCESSORY_DECODER )
{ {
uint16_t BoardAddress ; int16_t BoardAddress ;
uint16_t OutputAddress ; int16_t OutputAddress ;
uint8_t TurnoutPairIndex ; uint8_t TurnoutPairIndex ;
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
SerialPrintPacketHex(F( "execDccProcessor: Accessory Decoder Command: "), pDccMsg); SerialPrintPacketHex(F( "eDP: AccCmd: "), pDccMsg);
#endif #endif
BoardAddress = ( ( (~pDccMsg->Data[1]) & 0b01110000 ) << 2 ) | ( pDccMsg->Data[0] & 0b00111111 ) ; BoardAddress = ( ( (~pDccMsg->Data[1]) & 0b01110000 ) << 2 ) | ( pDccMsg->Data[0] & 0b00111111 ) ;
DB_PRINT("execDccProcessor: Board Addr: %d", BoardAddress); TurnoutPairIndex = (pDccMsg->Data[1] & 0b00000110) >> 1;
DB_PRINT("eDP: BAddr:%d, Index:%d", BoardAddress, TurnoutPairIndex);
// First check for Legacy Accessory Decoder Configuration Variable Access Instruction // First check for Legacy Accessory Decoder Configuration Variable Access Instruction
// as it's got a different format to the others // as it's got a different format to the others
if((pDccMsg->Size == 5) && ((pDccMsg->Data[1] & 0b10001100) == 0b00001100)) if((pDccMsg->Size == 5) && ((pDccMsg->Data[1] & 0b10001100) == 0b00001100))
{ {
DB_PRINT( "execDccProcessor: Legacy Accessory Decoder CV Access Command"); DB_PRINT( "eDP: Legacy Accessory Decoder CV Access Command");
// Check if this command is for our address or the broadcast address // Check if this command is for our address or the broadcast address
if((BoardAddress != getMyAddr()) && ( BoardAddress < 511 )) if((BoardAddress != getMyAddr()) && ( BoardAddress < 511 ))
{ {
DB_PRINT("execDccProcessor: Board Address Not Matched"); DB_PRINT("eDP: Board Address Not Matched");
return; return;
} }
uint16_t cvAddress = ((pDccMsg->Data[1] & 0b00000011) << 8) + pDccMsg->Data[2] + 1; uint16_t cvAddress = ((pDccMsg->Data[1] & 0b00000011) << 8) + pDccMsg->Data[2] + 1;
uint8_t cvValue = pDccMsg->Data[3]; uint8_t cvValue = pDccMsg->Data[3];
DB_PRINT("execDccProcessor: CV: %d Value: %d", cvAddress, cvValue ); DB_PRINT("eDP: CV:%d Value:%d", cvAddress, cvValue );
if(validCV( cvAddress, 1 )) if(validCV( cvAddress, 1 ))
writeCV(cvAddress, cvValue); writeCV(cvAddress, cvValue);
return; return;
} }
TurnoutPairIndex = (pDccMsg->Data[1] & 0b00000110) >> 1;
OutputAddress = (((BoardAddress - 1) << 2 ) | TurnoutPairIndex) + 1 ; //decoder output addresses start with 1, packet address range starts with 0 OutputAddress = (((BoardAddress - 1) << 2 ) | TurnoutPairIndex) + 1 ; //decoder output addresses start with 1, packet address range starts with 0
// ( according to NMRA 9.2.2 ) // ( according to NMRA 9.2.2 )
DB_PRINT("eDP: OAddr:%d", OutputAddress);
if( DccProcState.inAccDecDCCAddrNextReceivedMode) if( DccProcState.inAccDecDCCAddrNextReceivedMode)
{ {
if( DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE ) if( DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE )
{ {
DB_PRINT("execDccProcessor: Set Output Addr: %d", OutputAddress); DB_PRINT("eDP: Set OAddr:%d", OutputAddress);
//uint16_t storedOutputAddress = OutputAddress + 1; // The value stored in CV1 & 9 for Output Addressing Mode is + 1 //uint16_t storedOutputAddress = OutputAddress + 1; // The value stored in CV1 & 9 for Output Addressing Mode is + 1
writeCV(CV_ACCESSORY_DECODER_ADDRESS_LSB, (uint8_t)(OutputAddress % 256)); writeCV(CV_ACCESSORY_DECODER_ADDRESS_LSB, (uint8_t)(OutputAddress % 256));
writeCV(CV_ACCESSORY_DECODER_ADDRESS_MSB, (uint8_t)(OutputAddress / 256)); writeCV(CV_ACCESSORY_DECODER_ADDRESS_MSB, (uint8_t)(OutputAddress / 256));
@@ -1097,7 +1186,7 @@ void execDccProcessor( DCC_MSG * pDccMsg )
} }
else else
{ {
DB_PRINT("execDccProcessor: Set Board Addr: %d", BoardAddress); DB_PRINT("eDP: Set BAddr:%d", BoardAddress);
writeCV(CV_ACCESSORY_DECODER_ADDRESS_LSB, (uint8_t)(BoardAddress % 64)); writeCV(CV_ACCESSORY_DECODER_ADDRESS_LSB, (uint8_t)(BoardAddress % 64));
writeCV(CV_ACCESSORY_DECODER_ADDRESS_MSB, (uint8_t)(BoardAddress / 64)); writeCV(CV_ACCESSORY_DECODER_ADDRESS_MSB, (uint8_t)(BoardAddress / 64));
@@ -1111,21 +1200,34 @@ void execDccProcessor( DCC_MSG * pDccMsg )
// If we're filtering addresses, does the address match our address or is it a broadcast address? If NOT then return // If we're filtering addresses, does the address match our address or is it a broadcast address? If NOT then return
if( DccProcState.Flags & FLAGS_MY_ADDRESS_ONLY ) if( DccProcState.Flags & FLAGS_MY_ADDRESS_ONLY )
{ {
if( ( DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE ) && ( OutputAddress != getMyAddr() ) && ( OutputAddress < 2045 ) ) if( DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE ) {
DB_PRINT(" AddrChk: OAddr:%d, BAddr:%d, myAddr:%d Chk=%d", OutputAddress, BoardAddress, getMyAddr(), OutputAddress != getMyAddr() );
if ( OutputAddress != getMyAddr() && OutputAddress < 2045 ) {
DB_PRINT(" eDP: OAddr:%d, myAddr:%d - no match", OutputAddress, getMyAddr() );
return; return;
else if( ( BoardAddress != getMyAddr() ) && ( BoardAddress < 511 ) )
return;
DB_PRINT("execDccProcessor: Address Matched");
} }
} else {
if( ( BoardAddress != getMyAddr() ) && ( BoardAddress < 511 ) ) {
DB_PRINT(" eDP: BAddr:%d, myAddr:%d - no match", BoardAddress, getMyAddr() );
return;
}
}
DB_PRINT("eDP: Address Matched");
}
if((pDccMsg->Size == 4) && ((pDccMsg->Data[1] & 0b10001001) == 1)) // Extended Accessory Decoder Control Packet Format if((pDccMsg->Size == 4) && ((pDccMsg->Data[1] & 0b10001001) == 1)) // Extended Accessory Decoder Control Packet Format
{ {
uint8_t state = pDccMsg->Data[2] ;// & 0b00011111; // According to the NMRA Dcc Spec the Signal State should only use the lower 5 Bits,
DB_PRINT("execDccProcessor: Output Addr: %d Extended State: %0X", OutputAddress, state); // however some manufacturers seem to allow/use all 8 bits, so we'll relax that constraint for now
uint8_t state = pDccMsg->Data[2] ;
DB_PRINT("eDP: OAddr:%d Extended State:%0X", OutputAddress, state);
if( notifyDccSigOutputState ) if( notifyDccSigOutputState )
notifyDccSigOutputState(OutputAddress, state); notifyDccSigOutputState(OutputAddress, state);
// old callback ( for compatibility with 1.4.2, not to be used in new designs )
if( notifyDccSigState )
notifyDccSigState( OutputAddress, TurnoutPairIndex, pDccMsg->Data[2] ) ;
} }
else if(pDccMsg->Size == 3) // Basic Accessory Decoder Packet Format else if(pDccMsg->Size == 3) // Basic Accessory Decoder Packet Format
@@ -1133,49 +1235,49 @@ void execDccProcessor( DCC_MSG * pDccMsg )
uint8_t direction = pDccMsg->Data[1] & 0b00000001; uint8_t direction = pDccMsg->Data[1] & 0b00000001;
uint8_t outputPower = (pDccMsg->Data[1] & 0b00001000) >> 3; uint8_t outputPower = (pDccMsg->Data[1] & 0b00001000) >> 3;
// for compatibility with 1.4.2 // old callback ( for compatibility with 1.4.2, not to be used in new designs )
if ( notifyDccAccState ) if ( notifyDccAccState )
notifyDccAccState( OutputAddress, BoardAddress, pDccMsg->Data[1] & 0b00000111, outputPower ); notifyDccAccState( OutputAddress, BoardAddress, pDccMsg->Data[1] & 0b00000111, outputPower );
if( DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE ) if( DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE )
{ {
DB_PRINT("execDccProcessor: Output Addr: %d Turnout Dir: %d Output Power: %d", OutputAddress, direction, outputPower); DB_PRINT("eDP: OAddr:%d Turnout Dir:%d Output Power:%d", OutputAddress, direction, outputPower);
if( notifyDccAccTurnoutOutput ) if( notifyDccAccTurnoutOutput )
notifyDccAccTurnoutOutput( OutputAddress, direction, outputPower ); notifyDccAccTurnoutOutput( OutputAddress, direction, outputPower );
} }
else else
{ {
DB_PRINT("execDccProcessor: Turnout Pair Index: %d Dir: %d Output Power: ", TurnoutPairIndex, direction, outputPower); DB_PRINT("eDP: Turnout Pair Index:%d Dir:%d Output Power: ", TurnoutPairIndex, direction, outputPower);
if( notifyDccAccTurnoutBoard ) if( notifyDccAccTurnoutBoard )
notifyDccAccTurnoutBoard( BoardAddress, TurnoutPairIndex, direction, outputPower ); notifyDccAccTurnoutBoard( BoardAddress, TurnoutPairIndex, direction, outputPower );
} }
} }
else if(pDccMsg->Size == 6) // Accessory Decoder OPS Mode Programming else if(pDccMsg->Size == 6) // Accessory Decoder OPS Mode Programming
{ {
DB_PRINT("execDccProcessor: OPS Mode CV Programming Command"); DB_PRINT("eDP: OPS Mode CV Programming Command");
// Check for unsupported OPS Mode Addressing mode // Check for unsupported OPS Mode Addressing mode
if(((pDccMsg->Data[1] & 0b10001001) != 1) && ((pDccMsg->Data[1] & 0b10001111) != 0x80)) if(((pDccMsg->Data[1] & 0b10001001) != 1) && ((pDccMsg->Data[1] & 0b10001111) != 0x80))
{ {
DB_PRINT("execDccProcessor: Unsupported OPS Mode CV Addressing Mode"); DB_PRINT("eDP: Unsupported OPS Mode CV Addressing Mode");
return; return;
} }
// Check if this command is for our address or the broadcast address // Check if this command is for our address or the broadcast address
if(DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE) if(DccProcState.Flags & FLAGS_OUTPUT_ADDRESS_MODE)
{ {
DB_PRINT("execDccProcessor: Check Output Address: %d", OutputAddress); DB_PRINT("eDP: Check Output Address:%d", OutputAddress);
if((OutputAddress != getMyAddr()) && ( OutputAddress < 2045 )) if((OutputAddress != getMyAddr()) && ( OutputAddress < 2045 ))
{ {
DB_PRINT("execDccProcessor: Output Address Not Matched"); DB_PRINT("eDP: Output Address Not Matched");
return; return;
} }
} }
else else
{ {
DB_PRINT("execDccProcessor: Check Board Address: %d", BoardAddress); DB_PRINT("eDP: Check Board Address:%d", BoardAddress);
if((BoardAddress != getMyAddr()) && ( BoardAddress < 511 )) if((BoardAddress != getMyAddr()) && ( BoardAddress < 511 ))
{ {
DB_PRINT("execDccProcessor: Board Address Not Matched"); DB_PRINT("eDP: Board Address Not Matched");
return; return;
} }
} }
@@ -1185,16 +1287,16 @@ void execDccProcessor( DCC_MSG * pDccMsg )
OpsInstructionType insType = (OpsInstructionType)((pDccMsg->Data[2] & 0b00001100) >> 2) ; OpsInstructionType insType = (OpsInstructionType)((pDccMsg->Data[2] & 0b00001100) >> 2) ;
DB_PRINT("execDccProcessor: OPS Mode Instruction: %d", insType); DB_PRINT("eDP: OPS Mode Instruction:%d", insType);
switch(insType) switch(insType)
{ {
case OPS_INS_RESERVED: case OPS_INS_RESERVED:
case OPS_INS_VERIFY_BYTE: case OPS_INS_VERIFY_BYTE:
DB_PRINT("execDccProcessor: Unsupported OPS Mode Instruction: %d", insType); DB_PRINT("eDP: Unsupported OPS Mode Instruction:%d", insType);
break; // We only support Write Byte or Bit Manipulation break; // We only support Write Byte or Bit Manipulation
case OPS_INS_WRITE_BYTE: case OPS_INS_WRITE_BYTE:
DB_PRINT("execDccProcessor: CV: %d Value: %d", cvAddress, cvValue); DB_PRINT("eDP: CV:%d Value:%d", cvAddress, cvValue);
if(validCV( cvAddress, 1 )) if(validCV( cvAddress, 1 ))
writeCV(cvAddress, cvValue); writeCV(cvAddress, cvValue);
break; break;
@@ -1212,9 +1314,9 @@ void execDccProcessor( DCC_MSG * pDccMsg )
uint8_t currentValue = readCV(cvAddress); uint8_t currentValue = readCV(cvAddress);
uint8_t newValueMask = 1 << (cvValue & 0b00000111); uint8_t newValueMask = 1 << (cvValue & 0b00000111);
if(cvValue & 0b00001000) if(cvValue & 0b00001000)
writeCV(cvAddress, cvValue | newValueMask); writeCV(cvAddress, currentValue | newValueMask);
else else
writeCV(cvAddress, cvValue & ~newValueMask); writeCV(cvAddress, currentValue & ~newValueMask);
} }
break; break;
} }
@@ -1243,6 +1345,13 @@ NmraDcc::NmraDcc()
{ {
} }
#ifdef digitalPinToInterrupt
void NmraDcc::pin( uint8_t ExtIntPinNum, uint8_t EnablePullup)
{
pin(digitalPinToInterrupt(ExtIntPinNum), ExtIntPinNum, EnablePullup);
}
#endif
void NmraDcc::pin( uint8_t ExtIntNum, uint8_t ExtIntPinNum, uint8_t EnablePullup) void NmraDcc::pin( uint8_t ExtIntNum, uint8_t ExtIntPinNum, uint8_t EnablePullup)
{ {
#if defined ( __STM32F1__ ) #if defined ( __STM32F1__ )
@@ -1270,6 +1379,9 @@ void NmraDcc::init( uint8_t ManufacturerId, uint8_t VersionId, uint8_t Flags, ui
#if defined(ESP8266) #if defined(ESP8266)
EEPROM.begin(MAXCV); EEPROM.begin(MAXCV);
#endif #endif
#if defined(ESP32)
EEPROM.begin(MAXCV);
#endif
// Clear all the static member variables // Clear all the static member variables
memset( &DccRx, 0, sizeof( DccRx) ); memset( &DccRx, 0, sizeof( DccRx) );
@@ -1277,20 +1389,27 @@ void NmraDcc::init( uint8_t ManufacturerId, uint8_t VersionId, uint8_t Flags, ui
MODE_TP2; MODE_TP2;
MODE_TP3; MODE_TP3;
MODE_TP4; MODE_TP4;
ISREdge = RISING;
bitMax = MAX_ONEBITFULL; bitMax = MAX_ONEBITFULL;
bitMin = MIN_ONEBITFULL; bitMin = MIN_ONEBITFULL;
attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, RISING);
DccProcState.Flags = Flags ; DccProcState.Flags = Flags ;
DccProcState.OpsModeAddressBaseCV = OpsModeAddressBaseCV ; DccProcState.OpsModeAddressBaseCV = OpsModeAddressBaseCV ;
DccProcState.myDccAddress = -1; DccProcState.myDccAddress = -1;
DccProcState.inAccDecDCCAddrNextReceivedMode = 0; 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 // Set the Bits that control Multifunction or Accessory behaviour
// and if the Accessory decoder optionally handles Output Addressing // and if the Accessory decoder optionally handles Output Addressing
uint8_t cv29Mask = CV29_ACCESSORY_DECODER | CV29_OUTPUT_ADDRESS_MODE ; // peal off the top two bits // we need to peal off the top two bits
writeCV( CV_29_CONFIG, ( readCV( CV_29_CONFIG ) & ~cv29Mask ) | (Flags & cv29Mask) ) ; writeCV( CV_29_CONFIG, ( readCV( CV_29_CONFIG ) & ~FLAGS_CV29_BITS ) | (Flags & FLAGS_CV29_BITS) ) ;
uint8_t doAutoFactoryDefault = 0; uint8_t doAutoFactoryDefault = 0;
if((Flags & FLAGS_AUTO_FACTORY_DEFAULT) && (readCV(CV_VERSION_ID) == 255) && (readCV(CV_MANUFACTURER_ID) == 255)) if((Flags & FLAGS_AUTO_FACTORY_DEFAULT) && (readCV(CV_VERSION_ID) == 255) && (readCV(CV_MANUFACTURER_ID) == 255))
@@ -1314,7 +1433,13 @@ uint8_t NmraDcc::getCV( uint16_t CV )
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
uint8_t NmraDcc::setCV( uint16_t CV, uint8_t Value) uint8_t NmraDcc::setCV( uint16_t CV, uint8_t Value)
{ {
return writeCV(CV,Value); DccProcState.Flags |= FLAGS_SETCV_CALLED;
uint8_t returnValue = writeCV(CV,Value);
DccProcState.Flags &= ~FLAGS_SETCV_CALLED;
return returnValue;
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@@ -1384,10 +1509,19 @@ uint8_t NmraDcc::process()
{ {
// We need to do this check with interrupts disabled // We need to do this check with interrupts disabled
//SET_TP4; //SET_TP4;
#ifdef ESP32
portENTER_CRITICAL(&mux);
#else
noInterrupts(); noInterrupts();
#endif
Msg = DccRx.PacketCopy ; Msg = DccRx.PacketCopy ;
DccRx.DataReady = 0 ; DccRx.DataReady = 0 ;
#ifdef ESP32
portEXIT_CRITICAL(&mux);
#else
interrupts(); interrupts();
#endif
#ifdef DCC_DBGVAR #ifdef DCC_DBGVAR
countOf.Tel++; countOf.Tel++;
#endif #endif
@@ -1398,6 +1532,7 @@ uint8_t NmraDcc::process()
xorValue ^= DccRx.PacketCopy.Data[i]; xorValue ^= DccRx.PacketCopy.Data[i];
if(xorValue) { if(xorValue) {
#ifdef DCC_DBGVAR #ifdef DCC_DBGVAR
DB_PRINT("Cerr");
countOf.Err++; countOf.Err++;
#endif #endif
return 0 ; return 0 ;

View File

@@ -32,7 +32,7 @@
// Uncomment the following Line to Enable Service Mode CV Programming // Uncomment the following Line to Enable Service Mode CV Programming
#define NMRA_DCC_PROCESS_SERVICEMODE #define NMRA_DCC_PROCESS_SERVICEMODE
// Uncomment the following line to Enable MutliFunction Decoder Operations // Uncomment the following line to Enable MultiFunction Decoder Operations
#define NMRA_DCC_PROCESS_MULTIFUNCTION #define NMRA_DCC_PROCESS_MULTIFUNCTION
// Uncomment the following line to Enable 14 Speed Step Support // Uncomment the following line to Enable 14 Speed Step Support
@@ -49,7 +49,7 @@
#ifndef NMRADCC_IS_IN #ifndef NMRADCC_IS_IN
#define 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 #define MAX_DCC_MESSAGE_LEN 6 // including XOR-Byte
@@ -96,14 +96,17 @@ typedef struct
#define CV_MANUFACTURER_ID 8 #define CV_MANUFACTURER_ID 8
#define CV_29_CONFIG 29 #define CV_29_CONFIG 29
#if defined(ESP8266) #if defined(ESP32)
#include <spi_flash.h> #include <esp_log.h>
#define MAXCV SPI_FLASH_SEC_SIZE #define MAXCV SPI_FLASH_SEC_SIZE
#elif defined(ESP8266)
#include <spi_flash.h>
#define MAXCV SPI_FLASH_SEC_SIZE
#elif defined( __STM32F1__) #elif defined( __STM32F1__)
#define MAXCV (EEPROM_PAGE_SIZE/4 - 1) // number of storage places (CV address could be larger #define MAXCV (EEPROM_PAGE_SIZE/4 - 1) // number of storage places (CV address could be larger
// because STM32 uses virtual adresses) // because STM32 uses virtual adresses)
#else #else
#define MAXCV E2END // the upper limit of the CV value currently defined to max memory. #define MAXCV E2END // the upper limit of the CV value currently defined to max memory.
#endif #endif
typedef enum { typedef enum {
@@ -202,9 +205,14 @@ class NmraDcc
// Flag values to be logically ORed together and passed into the init() method // Flag values to be logically ORed together and passed into the init() method
#define FLAGS_MY_ADDRESS_ONLY 0x01 // Only process DCC Packets with My Address #define FLAGS_MY_ADDRESS_ONLY 0x01 // Only process DCC Packets with My Address
#define FLAGS_AUTO_FACTORY_DEFAULT 0x02 // Call notifyCVResetFactoryDefault() if CV 7 & 8 == 255 #define FLAGS_AUTO_FACTORY_DEFAULT 0x02 // Call notifyCVResetFactoryDefault() if CV 7 & 8 == 255
#define FLAGS_SETCV_CALLED 0x10 // only used internally !!
#define FLAGS_OUTPUT_ADDRESS_MODE 0x40 // CV 29/541 bit 6 #define FLAGS_OUTPUT_ADDRESS_MODE 0x40 // CV 29/541 bit 6
#define FLAGS_DCC_ACCESSORY_DECODER 0x80 // CV 29/541 bit 7 #define FLAGS_DCC_ACCESSORY_DECODER 0x80 // CV 29/541 bit 7
// Flag Bits that are cloned from CV29 relating the DCC Accessory Decoder
#define FLAGS_CV29_BITS (FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER)
/*+ /*+
* pin() is called from setup() and sets up the pin used to receive DCC packets. * pin() is called from setup() and sets up the pin used to receive DCC packets.
* *
@@ -218,6 +226,21 @@ class NmraDcc
*/ */
void pin( uint8_t ExtIntNum, uint8_t ExtIntPinNum, uint8_t EnablePullup); void pin( uint8_t ExtIntNum, uint8_t ExtIntPinNum, uint8_t EnablePullup);
/*+
* pin() is called from setup() and sets up the pin used to receive DCC packets.
* This relies on the internal function: digitalPinToInterrupt() to map the input pin number to the right interrupt
*
* Inputs:
* ExtIntPinNum - Input pin number.
* EnablePullup - Set true to enable the pins pullup resistor.
*
* Returns:
* None.
*/
#ifdef digitalPinToInterrupt
void pin( uint8_t ExtIntPinNum, uint8_t EnablePullup);
#endif
/*+ /*+
* init() is called from setup() after the pin() command is called. * init() is called from setup() after the pin() command is called.
* It initializes the NmDcc object and makes it ready to process packets. * It initializes the NmDcc object and makes it ready to process packets.
@@ -630,6 +653,8 @@ extern uint8_t notifyIsSetCVReady(void) __attribute__ ((weak));
/*+ /*+
* notifyCVChange() Called when a CV value is changed. * notifyCVChange() Called when a CV value is changed.
* This is called whenever a CV's value is changed. * This is called whenever a CV's value is changed.
* notifyDccCVChange() Called only when a CV value is changed by a Dcc packet or a internal lib function.
* it is NOT called if the CV is changed by means of the setCV() method.
* Note: It is not called if notifyCVWrite() is defined * Note: It is not called if notifyCVWrite() is defined
* or if the value in the EEPROM is the same as the value * or if the value in the EEPROM is the same as the value
* in the write command. * in the write command.
@@ -642,6 +667,7 @@ extern uint8_t notifyIsSetCVReady(void) __attribute__ ((weak));
* None * None
*/ */
extern void notifyCVChange( uint16_t CV, uint8_t Value) __attribute__ ((weak)); extern void notifyCVChange( uint16_t CV, uint8_t Value) __attribute__ ((weak));
extern void notifyDccCVChange( uint16_t CV, uint8_t Value) __attribute__ ((weak));
/*+ /*+
* notifyCVResetFactoryDefault() Called when CVs must be reset. * notifyCVResetFactoryDefault() Called when CVs must be reset.
@@ -672,10 +698,21 @@ extern void notifyCVResetFactoryDefault(void) __attribute__ ((weak));
* None * None
*/ */
extern void notifyCVAck(void) __attribute__ ((weak)); extern void notifyCVAck(void) __attribute__ ((weak));
/*+
* notifyServiceMode(bool) Called when state of 'inServiceMode' changes
*
* Inputs:
* bool state of inServiceMode
* *
* Returns:
* None
*/
extern void notifyServiceMode(bool) __attribute__ ((weak)); extern void notifyServiceMode(bool) __attribute__ ((weak));
// Deprecated, only for backward compatibility with version 1.4.2. Don't use in new designs // Deprecated, only for backward compatibility with version 1.4.2.
// Don't use in new designs. These functions may be dropped in future versions
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State ) __attribute__ ((weak)); extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State ) __attribute__ ((weak));
extern void notifyDccSigState( uint16_t Addr, uint8_t OutputIndex, uint8_t State) __attribute__ ((weak));
#if defined (__cplusplus) #if defined (__cplusplus)
} }

View File

@@ -0,0 +1,314 @@
// NMRA Dcc Multifunction Motor Decoder Demo
//
// Author: Alex Shepherd 2019-03-30
//
// This example requires these Arduino Libraries:
//
// 1) The NmraDcc Library from: http://mrrwa.org/download/
//
// These libraries can be found and installed via the Arduino IDE Library Manager
//
// This is a simple demo of how to drive and motor speed and direction using PWM and a motor H-Bridge
// It uses vStart and vHigh CV values to customise the PWM values to the motor response
// It also uses the Headling Function to drive 2 LEDs for Directional Headlights
// Apart from that there's nothing fancy like Lighting Effects or a function matrix or Speed Tables - its just the basics...
//
#include <NmraDcc.h>
// Uncomment any of the lines below to enable debug messages for different parts of the code
//#define DEBUG_FUNCTIONS
//#define DEBUG_SPEED
//#define DEBUG_PWM
//#define DEBUG_DCC_ACK
//#define DEBUG_DCC_MSG
#if defined(DEBUG_FUNCTIONS) or defined(DEBUG_SPEED) or defined(DEBUG_PWM) or defined(DEBUG_DCC_ACK) or defined(DEBUG_DCC_MSG)
#define DEBUG_PRINT
#endif
// This is the default DCC Address
#define DEFAULT_DECODER_ADDRESS 3
// This section defines the Arduino UNO Pins to use
#ifdef __AVR_ATmega328P__
#define DCC_PIN 2
#define LED_PIN_FWD 5
#define LED_PIN_REV 6
#define MOTOR_DIR_PIN 12
#define MOTOR_PWM_PIN 3
// This section defines the Arduino ATTiny85 Pins to use
#elif ARDUINO_AVR_ATTINYX5
#define DCC_PIN 2
#define LED_PIN_FWD 0
#define LED_PIN_REV 1
#define MOTOR_DIR_PIN 3
#define MOTOR_PWM_PIN 4
#else
#error "Unsupported CPU, you need to add another configuration section for your CPU"
#endif
// Some global state variables
uint8_t newLedState = 0;
uint8_t lastLedState = 0;
uint8_t newDirection = 0;
uint8_t lastDirection = 0;
uint8_t newSpeed = 0;
uint8_t lastSpeed = 0;
uint8_t numSpeedSteps = SPEED_STEP_128;
uint8_t vStart;
uint8_t vHigh;
// Structure for CV Values Table
struct CVPair
{
uint16_t CV;
uint8_t Value;
};
// CV Addresses we will be using
#define CV_VSTART 2
#define CV_VHIGH 5
// Default CV Values Table
CVPair FactoryDefaultCVs [] =
{
// The CV Below defines the Short DCC Address
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, DEFAULT_DECODER_ADDRESS},
// Three Step Speed Table
{CV_VSTART, 120},
{CV_VHIGH, 255},
// These two CVs define the Long DCC Address
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, DEFAULT_DECODER_ADDRESS},
// ONLY uncomment 1 CV_29_CONFIG line below as approprate
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
};
NmraDcc Dcc ;
uint8_t FactoryDefaultCVIndex = 0;
// This call-back function is called when a CV Value changes so we can update CVs we're using
void notifyCVChange( uint16_t CV, uint8_t Value)
{
switch(CV)
{
case CV_VSTART:
vStart = Value;
break;
case CV_VHIGH:
vHigh = Value;
break;
}
}
void notifyCVResetFactoryDefault()
{
// Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
// to flag to the loop() function that a reset to Factory Defaults needs to be done
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
};
// This call-back function is called whenever we receive a DCC Speed packet for our address
void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION Dir, DCC_SPEED_STEPS SpeedSteps )
{
#ifdef DEBUG_SPEED
Serial.print("notifyDccSpeed: Addr: ");
Serial.print(Addr,DEC);
Serial.print( (AddrType == DCC_ADDR_SHORT) ? "-S" : "-L" );
Serial.print(" Speed: ");
Serial.print(Speed,DEC);
Serial.print(" Steps: ");
Serial.print(SpeedSteps,DEC);
Serial.print(" Dir: ");
Serial.println( (Dir == DCC_DIR_FWD) ? "Forward" : "Reverse" );
#endif
newDirection = Dir;
newSpeed = Speed;
numSpeedSteps = SpeedSteps;
};
// This call-back function is called whenever we receive a DCC Function packet for our address
void notifyDccFunc(uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState)
{
#ifdef DEBUG_FUNCTIONS
Serial.print("notifyDccFunc: Addr: ");
Serial.print(Addr,DEC);
Serial.print( (AddrType == DCC_ADDR_SHORT) ? 'S' : 'L' );
Serial.print(" Function Group: ");
Serial.print(FuncGrp,DEC);
#endif
if(FuncGrp == FN_0_4)
{
newLedState = (FuncState & FN_BIT_00) ? 1 : 0;
#ifdef DEBUG_FUNCTIONS
Serial.print(" FN 0: ");
Serial.print(newLedState);
#endif
}
#ifdef DEBUG_FUNCTIONS
Serial.println();
#endif
}
// This call-back function is called whenever we receive a DCC Packet
#ifdef DEBUG_DCC_MSG
void notifyDccMsg( DCC_MSG * Msg)
{
Serial.print("notifyDccMsg: ") ;
for(uint8_t i = 0; i < Msg->Size; i++)
{
Serial.print(Msg->Data[i], HEX);
Serial.write(' ');
}
Serial.println();
}
#endif
// This call-back function is called by the NmraDcc library when a DCC ACK needs to be sent
// Calling this function should cause an increased 60ma current drain on the power supply for 6ms to ACK a CV Read
// So we will just turn the motor on for 8ms and then turn it off again.
void notifyCVAck(void)
{
#ifdef DEBUG_DCC_ACK
Serial.println("notifyCVAck") ;
#endif
digitalWrite(MOTOR_DIR_PIN, HIGH);
digitalWrite(MOTOR_PWM_PIN, HIGH);
delay( 8 );
digitalWrite(MOTOR_DIR_PIN, LOW);
digitalWrite(MOTOR_PWM_PIN, LOW);
}
void setup()
{
#ifdef DEBUG_PRINT
Serial.begin(115200);
Serial.println("NMRA Dcc Multifunction Motor Decoder Demo");
#endif
// Setup the Pins for the Fwd/Rev LED for Function 0 Headlight
pinMode(LED_PIN_FWD, OUTPUT);
pinMode(LED_PIN_REV, OUTPUT);
// Setup the Pins for the Motor H-Bridge Driver
pinMode(MOTOR_DIR_PIN, OUTPUT);
pinMode(MOTOR_PWM_PIN, OUTPUT);
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
Dcc.pin(DCC_PIN, 0);
Dcc.init( MAN_ID_DIY, 10, FLAGS_MY_ADDRESS_ONLY | FLAGS_AUTO_FACTORY_DEFAULT, 0 );
// Uncomment to force CV Reset to Factory Defaults
// notifyCVResetFactoryDefault();
// Read the current CV values for vStart and vHigh
vStart = Dcc.getCV(CV_VSTART);
vHigh = Dcc.getCV(CV_VHIGH);
}
void loop()
{
// You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation
Dcc.process();
// Handle Speed changes
if(lastSpeed != newSpeed)
{
lastSpeed = newSpeed;
// Stop if speed = 0 or 1
if(newSpeed <= 1)
digitalWrite(MOTOR_PWM_PIN, LOW);
// Calculate PWM value in the range 1..255
else
{
uint8_t vScaleFactor;
if((vHigh > 1) && (vHigh > vStart))
vScaleFactor = vHigh - vStart;
else
vScaleFactor = 255 - vStart;
uint8_t modSpeed = newSpeed - 1;
uint8_t modSteps = numSpeedSteps - 1;
uint8_t newPwm = (uint8_t) vStart + modSpeed * vScaleFactor / modSteps;
#ifdef DEBUG_PWM
Serial.print("New Speed: vStart: ");
Serial.print(vStart);
Serial.print(" vHigh: ");
Serial.print(vHigh);
Serial.print(" modSpeed: ");
Serial.print(modSpeed);
Serial.print(" vScaleFactor: ");
Serial.print(vScaleFactor);
Serial.print(" modSteps: ");
Serial.print(modSteps);
Serial.print(" newPwm: ");
Serial.println(newPwm);
#endif
analogWrite(MOTOR_PWM_PIN, newPwm);
}
}
// Handle Direction and Headlight changes
if((lastDirection != newDirection) || (lastLedState != newLedState))
{
lastDirection = newDirection;
lastLedState = newLedState;
digitalWrite(MOTOR_DIR_PIN, newDirection);
if(newLedState)
{
#ifdef DEBUG_FUNCTIONS
Serial.println("LED On");
#endif
digitalWrite(LED_PIN_FWD, newDirection ? LOW : HIGH);
digitalWrite(LED_PIN_REV, newDirection ? HIGH : LOW);
}
else
{
#ifdef DEBUG_FUNCTIONS
Serial.println("LED Off");
#endif
digitalWrite(LED_PIN_FWD, LOW);
digitalWrite(LED_PIN_REV, LOW);
}
}
// Handle resetting CVs back to Factory Defaults
if( FactoryDefaultCVIndex && Dcc.isSetCVReady())
{
FactoryDefaultCVIndex--; // Decrement first as initially it is the size of the array
Dcc.setCV( FactoryDefaultCVs[FactoryDefaultCVIndex].CV, FactoryDefaultCVs[FactoryDefaultCVIndex].Value);
}
}

View File

@@ -1,5 +1,5 @@
// Production 17 Switch Acessory DCC Decoder AccDec_10Servos_7LED_6Ftn.ino // Production 17 Switch Acessory DCC Decoder AccDec_10Servos_7LED_6Ftn.ino
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122) // Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122)
// ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES) // ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES)
// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255 // ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255
@@ -82,11 +82,14 @@ CVPair FactoryDefaultCVs [] =
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
// Speed Steps don't matter for this decoder // Speed Steps don't matter for this decoder
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS // ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps // {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps // {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps // {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
{CV_29_CONFIG,CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_F0_LOCATION}, // Accesory Decoder Short Address
// {CV_29_CONFIG, CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Accesory Decoder Long Address
{CV_DECODER_MASTER_RESET, 0}, {CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address {CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address
@@ -216,7 +219,7 @@ void setup() //******************************************************
// Setup which External Interrupt, the Pin it's associated with that we're using // Setup which External Interrupt, the Pin it's associated with that we're using
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 100, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); Dcc.init( MAN_ID_DIY, 601, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)

View File

@@ -1,6 +1,6 @@
// Production 17 Function DCC Decoder // Production 17 Function DCC Decoder
// Production 17 Switch Acessory DCC Decoder AccDec_13Servos_4LED_6Ftn.ino // Production 17 Switch Acessory DCC Decoder AccDec_13Servos_4LED_6Ftn.ino
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122) // Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122)
// ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES) // ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES)
// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255 // ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255
@@ -82,11 +82,14 @@ CVPair FactoryDefaultCVs [] =
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
// Speed Steps don't matter for this decoder // Speed Steps don't matter for this decoder
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS // ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps // {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps // {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps // {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
{CV_29_CONFIG,CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_F0_LOCATION}, // Accesory Decoder Short Address
// {CV_29_CONFIG, CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Accesory Decoder Long Address
{CV_DECODER_MASTER_RESET, 0}, {CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address {CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address
@@ -217,7 +220,7 @@ void setup() //******************************************************
// Setup which External Interrupt, the Pin it's associated with that we're using // Setup which External Interrupt, the Pin it's associated with that we're using
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 600, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); Dcc.init( MAN_ID_DIY, 601, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)

View File

@@ -1,5 +1,5 @@
// Production 17 Switch Acessory DCC Decoder AccDec_15Servos_2LED_6Ftn.ino // Production 17 Switch Acessory DCC Decoder AccDec_15Servos_2LED_6Ftn.ino
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122) // Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122)
// ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES) // ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES)
// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255 // ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255
@@ -81,11 +81,14 @@ CVPair FactoryDefaultCVs [] =
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
// Speed Steps don't matter for this decoder // Speed Steps don't matter for this decoder
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS // ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps // {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps // {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps // {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
{CV_29_CONFIG,CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_F0_LOCATION}, // Accesory Decoder Short Address
// {CV_29_CONFIG, CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Accesory Decoder Long Address
{CV_DECODER_MASTER_RESET, 0}, {CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address {CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address
@@ -216,7 +219,7 @@ void setup() //******************************************************
// Setup which External Interrupt, the Pin it's associated with that we're using // Setup which External Interrupt, the Pin it's associated with that we're using
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 600, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); Dcc.init( MAN_ID_DIY, 601, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)

13
examples/SMA/AccDec_17LED_1Ftn/AccDec_17LED_1Ftn.ino Executable file → Normal file
View File

@@ -1,5 +1,5 @@
// Production 17 Switch Acessory DCC Decoder AccDec_17LED_1Ftn.ino // Production 17 Switch Acessory DCC Decoder AccDec_17LED_1Ftn.ino
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122) // Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122)
// ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES) // ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES)
// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255 // ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255
@@ -56,11 +56,14 @@ CVPair FactoryDefaultCVs [] =
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
// Speed Steps don't matter for this decoder // Speed Steps don't matter for this decoder
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS // ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps // {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps // {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps // {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
{CV_29_CONFIG,CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_F0_LOCATION}, // Accesory Decoder Short Address
// {CV_29_CONFIG, CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Accesory Decoder Long Address
{CV_DECODER_MASTER_RESET, 0}, {CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address {CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address
@@ -105,7 +108,7 @@ void setup()
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up // Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 600, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); Dcc.init( MAN_ID_DIY, 601, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
} }
void loop() void loop()
{ {

13
examples/SMA/AccDec_17LED_6Ftn/AccDec_17LED_6Ftn.ino Executable file → Normal file
View File

@@ -1,5 +1,5 @@
// Production 17 Switch Acessory DCC Decoder AccDec_17LED_6Ftn.ino // Production 17 Switch Acessory DCC Decoder AccDec_17LED_6Ftn.ino
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122) // Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122)
// ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES) // ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES)
// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255 // ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255
@@ -81,11 +81,14 @@ CVPair FactoryDefaultCVs [] =
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
// Speed Steps don't matter for this decoder // Speed Steps don't matter for this decoder
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS // ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps // {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps // {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps // {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
{CV_29_CONFIG,CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_F0_LOCATION}, // Accesory Decoder Short Address
// {CV_29_CONFIG, CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Accesory Decoder Long Address
{CV_DECODER_MASTER_RESET, 0}, {CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address {CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address
@@ -219,7 +222,7 @@ void setup() //******************************************************
// Setup which External Interrupt, the Pin it's associated with that we're using // Setup which External Interrupt, the Pin it's associated with that we're using
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 600, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); Dcc.init( MAN_ID_DIY, 601, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)

View File

@@ -1,5 +1,5 @@
// Production 17 Switch Acessory DCC Decoder AccDec_7ServoBackandForth6Ftn.ino // Production 17 Switch Acessory DCC Decoder AccDec_7ServoBackandForth6Ftn.ino
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122) // Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122)
// ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES) // ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES)
// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255 // ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255
@@ -85,11 +85,14 @@ CVPair FactoryDefaultCVs [] =
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
// Speed Steps don't matter for this decoder // Speed Steps don't matter for this decoder
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS // ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps // {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps // {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps // {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
{CV_29_CONFIG,CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_F0_LOCATION}, // Accesory Decoder Short Address
// {CV_29_CONFIG, CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Accesory Decoder Long Address
{CV_DECODER_MASTER_RESET, 0}, {CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address {CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address
@@ -223,7 +226,7 @@ void setup() //******************************************************
// Setup which External Interrupt, the Pin it's associated with that we're using // Setup which External Interrupt, the Pin it's associated with that we're using
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 600, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); Dcc.init( MAN_ID_DIY, 601, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)

View File

@@ -1,5 +1,5 @@
// Production 17 Switch Acessory DCC Decoder AccDec_7Servos_10LED_6Ftn.ino // Production 17 Switch Acessory DCC Decoder AccDec_7Servos_10LED_6Ftn.ino
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122) // Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122)
// ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES) // ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES)
// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255 // ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255
@@ -81,11 +81,14 @@ CVPair FactoryDefaultCVs [] =
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
// Speed Steps don't matter for this decoder // Speed Steps don't matter for this decoder
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS // ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps // {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps // {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps // {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
{CV_29_CONFIG,CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_F0_LOCATION}, // Accesory Decoder Short Address
// {CV_29_CONFIG, CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Accesory Decoder Long Address
{CV_DECODER_MASTER_RESET, 0}, {CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address {CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address
@@ -219,7 +222,7 @@ void setup() //******************************************************
// Setup which External Interrupt, the Pin it's associated with that we're using // Setup which External Interrupt, the Pin it's associated with that we're using
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 600, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); Dcc.init( MAN_ID_DIY, 601, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)

View File

@@ -1,5 +1,5 @@
// Production 17 Function DCC Decoder // Production 17 Function DCC Decoder
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses // Now works with both short and long DCC Addesses
// NO LONGER REQUIRES modified software servo Lib // NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter // Software restructuring mods added from Alex Shepherd and Franz-Peter
@@ -211,7 +211,7 @@ void setup() //******************************************************
// Setup which External Interrupt, the Pin it's associated with that we're using // Setup which External Interrupt, the Pin it's associated with that we're using
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)

View File

@@ -1,5 +1,5 @@
// Production 17 Function DCC Decoder Dec_13Serv_4LED_6Ftn.ino // Production 17 Function DCC Decoder Dec_13Serv_4LED_6Ftn.ino
// Version 5.4 Geoff Bunza 2014,2015,2016 // Version 6.01 Geoff Bunza 2014,2015,2016
// NO LONGER REQUIRES modified software servo Lib // NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter // Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks // With sincere thanks
@@ -12,7 +12,6 @@
// ******** INFO TO THE SERIAL MONITOR // ******** INFO TO THE SERIAL MONITOR
//#define DEBUG //#define DEBUG
#include <NmraDcc.h> #include <NmraDcc.h>
#include <SoftwareServo.h> #include <SoftwareServo.h>
@@ -208,7 +207,7 @@ void setup() //******************************************************
// Setup which External Interrupt, the Pin it's associated with that we're using // Setup which External Interrupt, the Pin it's associated with that we're using
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 ); Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)

View File

@@ -1,5 +1,5 @@
// Production 17 Function DCC Decoder Dec_15Serv_2LED_6Ftn.ino // Production 17 Function DCC Decoder Dec_15Serv_2LED_6Ftn.ino
// Version 5.4 Geoff Bunza 2014,2015,2016 // Version 6.01 Geoff Bunza 2014,2015,2016
// NO LONGER REQUIRES modified software servo Lib // NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter // Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks // With sincere thanks
@@ -68,10 +68,17 @@ struct CVPair
CVPair FactoryDefaultCVs [] = CVPair FactoryDefaultCVs [] =
{ {
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address}, {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F },
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, // These two CVs define the Long DCC Address
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 },
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF },
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
{CV_DECODER_MASTER_RESET, 0}, {CV_DECODER_MASTER_RESET, 0},
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate {31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate
@@ -200,7 +207,7 @@ void setup() //******************************************************
// Setup which External Interrupt, the Pin it's associated with that we're using // Setup which External Interrupt, the Pin it's associated with that we're using
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 ); Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)

4
examples/SMA/Dec_17LED_1Ftn/Dec_17LED_1Ftn.ino Executable file → Normal file
View File

@@ -1,5 +1,5 @@
// Production 17 Function DCC Decoder Dec_17LED_1Ftn.ino // Production 17 Function DCC Decoder Dec_17LED_1Ftn.ino
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses // Now works with both short and long DCC Addesses
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP // ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
@@ -87,7 +87,7 @@ void setup()
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up // Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET ) if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )

4
examples/SMA/Dec_17LED_6Ftn/Dec_17LED_6Ftn.ino Executable file → Normal file
View File

@@ -1,5 +1,5 @@
// Production 17 Function DCC Decoder Dec_17LED_6Ftn.ino // Production 17 Function DCC Decoder Dec_17LED_6Ftn.ino
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses // Now works with both short and long DCC Addesses
// NO LONGER REQUIRES modified software servo Lib // NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter // Software restructuring mods added from Alex Shepherd and Franz-Peter
@@ -211,7 +211,7 @@ void setup() //******************************************************
// Setup which External Interrupt, the Pin it's associated with that we're using // Setup which External Interrupt, the Pin it's associated with that we're using
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)

View File

@@ -1,7 +1,7 @@
// Production 2 Motor 13 Function DCC Decoder Dec_2MotDrive_12LED_1Srv_6Ftn.ino // Production 2 Motor 13 Function DCC Decoder Dec_2MotDrive_12LED_1Srv_6Ftn.ino
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01a Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses // Now works with both short and long DCC Addesses
// Better motor control added
// NO LONGER REQUIRES modified software servo Lib // NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter // Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks // With sincere thanks
@@ -35,12 +35,10 @@ SoftwareServo servo[13];
#define servo_slowdown 12 //servo loop counter limit #define servo_slowdown 12 //servo loop counter limit
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
uint8_t Motor1Speed = 0; int Motor1Speed = 0;
uint8_t Motor1ForwardDir = 1; uint8_t Motor1ForwardDir = 1;
uint8_t Motor1MaxSpeed = 127; int Motor2Speed = 0;
uint8_t Motor2Speed = 0;
uint8_t Motor2ForwardDir = 1; uint8_t Motor2ForwardDir = 1;
uint8_t Motor2MaxSpeed = 127;
int kickstarton = 1400; //kick start cycle on time int kickstarton = 1400; //kick start cycle on time
int kickstarttime = 5; //kick start duration on time int kickstarttime = 5; //kick start duration on time
int fwdon = 0; int fwdon = 0;
@@ -49,6 +47,7 @@ int bwdon = 0;
int bwdtime = 1; int bwdtime = 1;
int bwdshift = 0; int bwdshift = 0;
int cyclewidth = 2047; int cyclewidth = 2047;
int loopdelay =14;
int m2h = 3; //R H Bridge //Motor1 int m2h = 3; //R H Bridge //Motor1
int m2l = 4; //B H Bridge //Motor1 int m2l = 4; //B H Bridge //Motor1
int m0h = 9; //R H Bridge //Motor2 int m0h = 9; //R H Bridge //Motor2
@@ -56,7 +55,7 @@ int m0l = 10; //B H Bridge //Motor2
int speedup = 112; //Right track time differntial int speedup = 112; //Right track time differntial
int deltime = 1500; int deltime = 1500;
int tim_delay = 80; int tim_delay = 30;
int numfpins = 17; int numfpins = 17;
int num_active_fpins = 13; int num_active_fpins = 13;
byte fpins [] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; byte fpins [] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
@@ -71,7 +70,6 @@ const int FunctionPin6 = 13;
const int FunctionPin7 = 14; //A0 const int FunctionPin7 = 14; //A0
const int FunctionPin8 = 15; //A1 const int FunctionPin8 = 15; //A1
const int FunctionPin9 = 16; //A2 const int FunctionPin9 = 16; //A2
const int FunctionPin10 = 17; //A3 const int FunctionPin10 = 17; //A3
const int FunctionPin11 = 18; //A4 const int FunctionPin11 = 18; //A4
@@ -111,9 +109,9 @@ CVPair FactoryDefaultCVs [] =
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF }, {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF },
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS // ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps // {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps // {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
{CV_DECODER_MASTER_RESET, 0}, {CV_DECODER_MASTER_RESET, 0},
{30, 0}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {30, 0}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
@@ -244,7 +242,7 @@ void setup() //******************************************************
// Setup which External Interrupt, the Pin it's associated with that we're using // Setup which External Interrupt, the Pin it's associated with that we're using
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)
@@ -340,13 +338,27 @@ void loop() //****************************************************************
Dcc.process(); Dcc.process();
SoftwareServo::refresh(); SoftwareServo::refresh();
delay(2); delay(2);
#ifdef DEBUG
Serial.print("Motor1Speed= ");
Serial.println(Motor1Speed, DEC) ;
Serial.print("Motor2Speed= ");
Serial.println(Motor2Speed, DEC) ;
#endif
if (Motor1Speed != 0) { if (Motor1Speed != 0) {
if (Motor1ForwardDir == 0) gofwd1 (fwdtime, int((Motor1Speed&0x7f)*21)); if (Motor1ForwardDir == 0) gofwd1 (fwdtime, Motor1Speed<<4);
else gobwd1 (bwdtime, int((Motor1Speed&0x7f)*21)); else gobwd1 (bwdtime, Motor1Speed<<4);
}
else {
digitalWrite(m2h, LOW); //Motor1 OFF
digitalWrite(m2l, LOW); //Motor1 OFF
} }
if (Motor2Speed != 0) { if (Motor2Speed != 0) {
if (Motor2ForwardDir == 0) gofwd2 (fwdtime, int((Motor2Speed&0x7f)*21)); if (Motor2ForwardDir == 0) gofwd2 (fwdtime, Motor2Speed<<4);
else gobwd2 (bwdtime, int((Motor2Speed&0x7f)*21)); else gobwd2 (bwdtime, Motor2Speed<<4);
}
else {
digitalWrite(m0h, LOW); //Motor1 OFF
digitalWrite(m0l, LOW); //Motor1 OFF
} }
// //
for (int i=0; i < num_active_fpins; i++) { for (int i=0; i < num_active_fpins; i++) {
@@ -420,61 +432,73 @@ void loop() //****************************************************************
} }
void gofwd1(int fcnt,int fcycle) { void gofwd1(int fcnt,int fcycle) {
int icnt; int icnt;
int totcycle; int delta_tp,delta_tm;
delta_tp = fcycle+loopdelay<<2;
delta_tm = cyclewidth-fcycle-loopdelay;
icnt = 0; icnt = 0;
while (icnt < fcnt) while (icnt < fcnt)
{ {
digitalWrite(m2h, HIGH); //Motor1 digitalWrite(m2h, HIGH); //Motor1
delayMicroseconds(fcycle); delayMicroseconds(delta_tp);
digitalWrite(m2h, LOW); //Motor1 digitalWrite(m2h, LOW); //Motor1
delayMicroseconds(cyclewidth - fcycle); delayMicroseconds(delta_tm);
icnt++; icnt++;
} }
} }
void gobwd1(int bcnt,int bcycle) { void gobwd1(int bcnt,int bcycle) {
int icnt; int icnt;
int delta_tp,delta_tm;
delta_tp = bcycle+loopdelay<<2;
delta_tm = cyclewidth-bcycle-loopdelay;
icnt=0; icnt=0;
while (icnt < bcnt) while (icnt < bcnt)
{ {
digitalWrite(m2l, HIGH); //Motor1 digitalWrite(m2l, HIGH); //Motor1
delayMicroseconds(bcycle); delayMicroseconds(delta_tp);
digitalWrite(m2l, LOW); //Motor1 digitalWrite(m2l, LOW); //Motor1
delayMicroseconds(cyclewidth - bcycle); delayMicroseconds(delta_tm);
icnt++; icnt++;
} }
} }
void gofwd2(int fcnt,int fcycle) { void gofwd2(int fcnt,int fcycle) {
int icnt; int icnt;
int totcycle; int delta_tp,delta_tm;
delta_tp = fcycle+loopdelay<<2;
delta_tm = cyclewidth-fcycle-loopdelay;
icnt = 0; icnt = 0;
while (icnt < fcnt) while (icnt < fcnt)
{ {
digitalWrite(m0h, HIGH); //Motor2 digitalWrite(m0h, HIGH); //Motor2
delayMicroseconds(fcycle); delayMicroseconds(delta_tp);
digitalWrite(m0h, LOW); //Motor2 digitalWrite(m0h, LOW); //Motor2
delayMicroseconds(cyclewidth - fcycle); delayMicroseconds(delta_tm);
icnt++; icnt++;
} }
} }
void gobwd2(int bcnt,int bcycle) { void gobwd2(int bcnt,int bcycle) {
int icnt; int icnt;
int delta_tp,delta_tm;
delta_tp = bcycle+loopdelay<<2;
delta_tm = cyclewidth-bcycle-loopdelay;
icnt=0; icnt=0;
while (icnt < bcnt) while (icnt < bcnt)
{ {
digitalWrite(m0l, HIGH); //Motor2 digitalWrite(m0l, HIGH); //Motor2
delayMicroseconds(bcycle); delayMicroseconds(delta_tp);
digitalWrite(m0l, LOW); //Motor2 digitalWrite(m0l, LOW); //Motor2
delayMicroseconds(cyclewidth - bcycle); delayMicroseconds(delta_tm);
icnt++; icnt++;
} }
} }
void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION ForwardDir, DCC_SPEED_STEPS SpeedSteps ) { void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION ForwardDir, DCC_SPEED_STEPS SpeedSteps ) {
if (Function13_value==1) { if (Function13_value==1) {
Motor1Speed = Speed; Motor1Speed = (Speed & 0x7f );
if (Motor1Speed == 1) Motor1Speed=0;
Motor1ForwardDir = ForwardDir; Motor1ForwardDir = ForwardDir;
} }
if (Function14_value==1) { if (Function14_value==1) {
Motor2Speed = Speed; Motor2Speed = (Speed & 0x7f );
if (Motor2Speed == 1) Motor2Speed=0;
Motor2ForwardDir = ForwardDir; Motor2ForwardDir = ForwardDir;
} }
} }

View File

@@ -1,7 +1,7 @@
// Production 2 Motor w/Triggered Audio Multi Function DCC Decoder Dec_2Mot_3LED_TrigAudio.ino // Production 2 Motor w/Triggered Audio Multi Function DCC Decoder Dec_2Mot_3LED_TrigAudio.ino
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01a Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses // Now works with both short and long DCC Addesses
// Improved motor control added
// This decoder will control 2 motors and play audio clips by function: // This decoder will control 2 motors and play audio clips by function:
// F0=LED on pin 8, F1-F4 Controls playing specific audio tracks in the 3rd CV (start) at the volume in the 2nd CV (rate) // F0=LED on pin 8, F1-F4 Controls playing specific audio tracks in the 3rd CV (start) at the volume in the 2nd CV (rate)
// F5 Controls playing audio track in CV57 at the volume in CV56 ONLY when F5 is ON and Pin17/A3 is held low, // F5 Controls playing audio track in CV57 at the volume in CV56 ONLY when F5 is ON and Pin17/A3 is held low,
@@ -21,7 +21,7 @@
* Motor speed for each can only be changed if the corresponding Function is on * Motor speed for each can only be changed if the corresponding Function is on
* (F13 and/or F14). Motor speed is maintained if the corresponding Motor select function * (F13 and/or F14). Motor speed is maintained if the corresponding Motor select function
* is off. Thus, each motor can be controlled independently and run at different speeds. * is off. Thus, each motor can be controlled independently and run at different speeds.
* F0 LED Pin 8 * F0 LED Pin 13
* F1-F6 6 Functions Configures As Audio Play * F1-F6 6 Functions Configures As Audio Play
* F7-F8 2 Functions Configures As LEDs by default PINS 18 and 19 * F7-F8 2 Functions Configures As LEDs by default PINS 18 and 19
* F13 Motor1 Control Enable * F13 Motor1 Control Enable
@@ -68,12 +68,10 @@ SoftwareServo servo[10];
#define servo_slowdown 4 //servo loop counter limit #define servo_slowdown 4 //servo loop counter limit
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
uint8_t Motor1Speed = 0; int Motor1Speed = 0;
uint8_t Motor1ForwardDir = 1; uint8_t Motor1ForwardDir = 1;
uint8_t Motor1MaxSpeed = 127; int Motor2Speed = 0;
uint8_t Motor2Speed = 0;
uint8_t Motor2ForwardDir = 1; uint8_t Motor2ForwardDir = 1;
uint8_t Motor2MaxSpeed = 127;
int kickstarton = 1400; //kick start cycle on time int kickstarton = 1400; //kick start cycle on time
int kickstarttime = 5; //kick start duration on time int kickstarttime = 5; //kick start duration on time
int fwdon = 0; int fwdon = 0;
@@ -82,6 +80,7 @@ int bwdon = 0;
int bwdtime = 1; int bwdtime = 1;
int bwdshift = 0; int bwdshift = 0;
int cyclewidth = 2047; int cyclewidth = 2047;
int loopdelay =14;
int m2h = 3; //R H Bridge //Motor1 int m2h = 3; //R H Bridge //Motor1
int m2l = 4; //B H Bridge //Motor1 int m2l = 4; //B H Bridge //Motor1
int m0h = 9; //R H Bridge //Motor2 int m0h = 9; //R H Bridge //Motor2
@@ -89,31 +88,31 @@ int m0l = 10; //B H Bridge //Motor2
int speedup = 112; //Right track time differntial int speedup = 112; //Right track time differntial
int deltime = 1500; int deltime = 1500;
int tim_delay = 100; int tim_delay = 30;
int numfpins = 13; int numfpins = 13;
int num_active_fpins = 9; int num_active_fpins = 9;
byte fpins [] = {3,4,8,9,10,11,12,13,14,15,16,18}; byte fpins [] = {3,4,8,9,10,11,12,13,14,15,16,18};
const int FunctionPin0 = 8; const int FunctionPin0 = 13;
const int FunctionPin1 = 11; const int FunctionPin1 = 20; // Place holders ONLY
const int FunctionPin2 = 12; const int FunctionPin2 = 20; // Place holders ONLY
const int FunctionPin3 = 13; const int FunctionPin3 = 20; // Place holders ONLY
const int FunctionPin4 = 14; //A0 const int FunctionPin4 = 20; //A0 Place holders ONLY
const int FunctionPin5 = 15; //A1 const int FunctionPin5 = 20; //A1 Place holders ONLY
const int FunctionPin6 = 16; //A2 const int FunctionPin6 = 20; //A2 Place holders ONLY
const int FunctionPin7 = 18; //A5 const int FunctionPin7 = 18; //A5 Place holders ONLY
const int FunctionPin8 = 19; //A4 const int FunctionPin8 = 19; //A4 Place holders ONLY
const int AudioTriggerPin = 17; //A3 NOW USED AS Audio Trigger Pin INPUT_PULLUP const int AudioTriggerPin = 17; //A3 NOW USED AS Audio Trigger Pin INPUT_PULLUP
const int FunctionPin9 = 20; // Place holders ONLY const int FunctionPin9 = 20; // Place holders ONLY
const int FunctionPin10 = 20; // Place holders ONLY const int FunctionPin10 = 20; // Place holders ONLY
const int FunctionPin11 = 20; const int FunctionPin11 = 20; // Place holders ONLY
const int FunctionPin12 = 20; const int FunctionPin12 = 20; // Place holders ONLY
const int FunctionPin13 = 20; const int FunctionPin13 = 20; // Place holders ONLY
const int FunctionPin14 = 20; const int FunctionPin14 = 20; // Place holders ONLY
const int FunctionPin15 = 20; const int FunctionPin15 = 20; // Place holders ONLY
const int FunctionPin16 = 20; const int FunctionPin16 = 20; // Place holders ONLY
int Function13_value = 0; int Function13_value = 0;
int Function14_value = 0; int Function14_value = 0;
@@ -122,7 +121,6 @@ NmraDcc Dcc ;
DCC_MSG Packet ; DCC_MSG Packet ;
uint8_t CV_DECODER_MASTER_RESET = 120; uint8_t CV_DECODER_MASTER_RESET = 120;
int t; // temp int t; // temp
struct QUEUE struct QUEUE
{ {
int inuse; int inuse;
@@ -242,7 +240,7 @@ void setup() //******************************************************
// Setup which External Interrupt, the Pin it's associated with that we're using // Setup which External Interrupt, the Pin it's associated with that we're using
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)
@@ -354,13 +352,27 @@ void loop() //****************************************************************
Dcc.process(); Dcc.process();
SoftwareServo::refresh(); SoftwareServo::refresh();
delay(2); delay(2);
#ifdef DEBUG
Serial.print("Motor1Speed= ");
Serial.println(Motor1Speed, DEC) ;
Serial.print("Motor2Speed= ");
Serial.println(Motor2Speed, DEC) ;
#endif
if (Motor1Speed != 0) { if (Motor1Speed != 0) {
if (Motor1ForwardDir == 0) gofwd1 (fwdtime, int((Motor1Speed&0x7f)*21)); if (Motor1ForwardDir == 0) gofwd1 (fwdtime, Motor1Speed<<4);
else gobwd1 (bwdtime, int((Motor1Speed&0x7f)*21)); else gobwd1 (bwdtime, Motor1Speed<<4);
}
else {
digitalWrite(m2h, LOW); //Motor1 OFF
digitalWrite(m2l, LOW); //Motor1 OFF
} }
if (Motor2Speed != 0) { if (Motor2Speed != 0) {
if (Motor2ForwardDir == 0) gofwd2 (fwdtime, int((Motor2Speed&0x7f)*21)); if (Motor2ForwardDir == 0) gofwd2 (fwdtime, Motor2Speed<<4);
else gobwd2 (bwdtime, int((Motor2Speed&0x7f)*21)); else gobwd2 (bwdtime, Motor2Speed<<4);
}
else {
digitalWrite(m0h, LOW); //Motor1 OFF
digitalWrite(m0l, LOW); //Motor1 OFF
} }
// //
for (int i=0; i < num_active_fpins; i++) { for (int i=0; i < num_active_fpins; i++) {
@@ -460,61 +472,73 @@ void loop() //****************************************************************
} }
void gofwd1(int fcnt,int fcycle) { void gofwd1(int fcnt,int fcycle) {
int icnt; int icnt;
int totcycle; int delta_tp,delta_tm;
delta_tp = fcycle+loopdelay<<2;
delta_tm = cyclewidth-fcycle-loopdelay;
icnt = 0; icnt = 0;
while (icnt < fcnt) while (icnt < fcnt)
{ {
digitalWrite(m2h, HIGH); //Motor1 digitalWrite(m2h, HIGH); //Motor1
delayMicroseconds(fcycle); delayMicroseconds(delta_tp);
digitalWrite(m2h, LOW); //Motor1 digitalWrite(m2h, LOW); //Motor1
delayMicroseconds(cyclewidth - fcycle); delayMicroseconds(delta_tm);
icnt++; icnt++;
} }
} }
void gobwd1(int bcnt,int bcycle) { void gobwd1(int bcnt,int bcycle) {
int icnt; int icnt;
int delta_tp,delta_tm;
delta_tp = bcycle+loopdelay<<2;
delta_tm = cyclewidth-bcycle-loopdelay;
icnt=0; icnt=0;
while (icnt < bcnt) while (icnt < bcnt)
{ {
digitalWrite(m2l, HIGH); //Motor1 digitalWrite(m2l, HIGH); //Motor1
delayMicroseconds(bcycle); delayMicroseconds(delta_tp);
digitalWrite(m2l, LOW); //Motor1 digitalWrite(m2l, LOW); //Motor1
delayMicroseconds(cyclewidth - bcycle); delayMicroseconds(delta_tm);
icnt++; icnt++;
} }
} }
void gofwd2(int fcnt,int fcycle) { void gofwd2(int fcnt,int fcycle) {
int icnt; int icnt;
int totcycle; int delta_tp,delta_tm;
delta_tp = fcycle+loopdelay<<2;
delta_tm = cyclewidth-fcycle-loopdelay;
icnt = 0; icnt = 0;
while (icnt < fcnt) while (icnt < fcnt)
{ {
digitalWrite(m0h, HIGH); //Motor2 digitalWrite(m0h, HIGH); //Motor2
delayMicroseconds(fcycle); delayMicroseconds(delta_tp);
digitalWrite(m0h, LOW); //Motor2 digitalWrite(m0h, LOW); //Motor2
delayMicroseconds(cyclewidth - fcycle); delayMicroseconds(delta_tm);
icnt++; icnt++;
} }
} }
void gobwd2(int bcnt,int bcycle) { void gobwd2(int bcnt,int bcycle) {
int icnt; int icnt;
int delta_tp,delta_tm;
delta_tp = bcycle+loopdelay<<2;
delta_tm = cyclewidth-bcycle-loopdelay;
icnt=0; icnt=0;
while (icnt < bcnt) while (icnt < bcnt)
{ {
digitalWrite(m0l, HIGH); //Motor2 digitalWrite(m0l, HIGH); //Motor2
delayMicroseconds(bcycle); delayMicroseconds(delta_tp);
digitalWrite(m0l, LOW); //Motor2 digitalWrite(m0l, LOW); //Motor2
delayMicroseconds(cyclewidth - bcycle); delayMicroseconds(delta_tm);
icnt++; icnt++;
} }
} }
void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION ForwardDir, DCC_SPEED_STEPS SpeedSteps ) { void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION ForwardDir, DCC_SPEED_STEPS SpeedSteps ) {
if (Function13_value==1) { if (Function13_value==1) {
Motor1Speed = Speed; Motor1Speed = (Speed & 0x7f );
if (Motor1Speed == 1) Motor1Speed=0;
Motor1ForwardDir = ForwardDir; Motor1ForwardDir = ForwardDir;
} }
if (Function14_value==1) { if (Function14_value==1) {
Motor2Speed = Speed; Motor2Speed = (Speed & 0x7f );
if (Motor2Speed == 1) Motor2Speed=0;
Motor2ForwardDir = ForwardDir; Motor2ForwardDir = ForwardDir;
} }
} }

View File

@@ -1,6 +1,14 @@
// Production 2 Motor w/Audio 13 Function DCC Decoder Dec_2Mot_10LED_Audio_8Ftn.ino // Production 2 Motor w/Audio 13 Function DCC Decoder Dec_2Mot_10LED_Audio_8Ftn.ino
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01a Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses // Now works with both short and long DCC Addesses
// Improved motor control added
// This decoder will control 2 motors and play audio clips by function:
// F0=LED on pin 13, F1-F4 Controls playing specific audio tracks in the 3rd CV (start) at the volume in the 2nd CV (rate)
// F5 Controls playing audio track in CV57 at the volume in CV56 ONLY when F5 is ON and Pin17/A3 is held low,
// and plays continuously until F5 turns off or Pin17 trigger goes HIGH or open
// F6 plays one track selected randomly off the memory card
// F13 and F14 select each separate motor which will respond to speed and direction controls
// F7-F8 control LEDs by default PINS 18 and 19
// NO LONGER REQUIRES modified software servo Lib // NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter // Software restructuring mods added from Alex Shepherd and Franz-Peter
@@ -10,7 +18,7 @@
* Motor speed for each can only be changed if the corresponding Function is on * Motor speed for each can only be changed if the corresponding Function is on
* (F13 and/or F14). Motor speed is maintained if the corresponding Motor select function * (F13 and/or F14). Motor speed is maintained if the corresponding Motor select function
* is off. Thus, each motor can be controlled independently and run at different speeds. * is off. Thus, each motor can be controlled independently and run at different speeds.
* F0 LED Pin 8 * F0 LED Pin 13
* F1-F6 6 Functions Configures As Audio Play * F1-F6 6 Functions Configures As Audio Play
* F7-F9 3 Functions Configures As LEDs * F7-F9 3 Functions Configures As LEDs
* F13 Motor1 Control Enable * F13 Motor1 Control Enable
@@ -57,12 +65,10 @@ SoftwareServo servo[10];
#define servo_slowdown 4 //servo loop counter limit #define servo_slowdown 4 //servo loop counter limit
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
uint8_t Motor1Speed = 0; int Motor1Speed = 0;
uint8_t Motor1ForwardDir = 1; uint8_t Motor1ForwardDir = 1;
uint8_t Motor1MaxSpeed = 127; int Motor2Speed = 0;
uint8_t Motor2Speed = 0;
uint8_t Motor2ForwardDir = 1; uint8_t Motor2ForwardDir = 1;
uint8_t Motor2MaxSpeed = 127;
int kickstarton = 1400; //kick start cycle on time int kickstarton = 1400; //kick start cycle on time
int kickstarttime = 5; //kick start duration on time int kickstarttime = 5; //kick start duration on time
int fwdon = 0; int fwdon = 0;
@@ -71,6 +77,7 @@ int bwdon = 0;
int bwdtime = 1; int bwdtime = 1;
int bwdshift = 0; int bwdshift = 0;
int cyclewidth = 2047; int cyclewidth = 2047;
int loopdelay =14;
int m2h = 3; //R H Bridge //Motor1 int m2h = 3; //R H Bridge //Motor1
int m2l = 4; //B H Bridge //Motor1 int m2l = 4; //B H Bridge //Motor1
int m0h = 9; //R H Bridge //Motor2 int m0h = 9; //R H Bridge //Motor2
@@ -78,29 +85,31 @@ int m0l = 10; //B H Bridge //Motor2
int speedup = 112; //Right track time differntial int speedup = 112; //Right track time differntial
int deltime = 1500; int deltime = 1500;
int tim_delay = 100; int tim_delay = 30;
int numfpins = 14; int numfpins = 14;
int num_active_fpins = 10; int num_active_fpins = 10;
byte fpins [] = {3,4,8,9,10,11,12,13,14,15,16,17,18,19}; byte fpins [] = {3,4,8,9,10,11,12,13,14,15,16,17,18,19};
const int FunctionPin0 = 8; const int FunctionPin0 = 13;
const int FunctionPin1 = 11; const int FunctionPin1 = 20; // Place holders ONLY
const int FunctionPin2 = 12; const int FunctionPin2 = 20; // Place holders ONLY
const int FunctionPin3 = 13; const int FunctionPin3 = 20; // Place holders ONLY
const int FunctionPin4 = 14; //A0 const int FunctionPin4 = 20; //A0 Place holders ONLY
const int FunctionPin5 = 15; //A1 const int FunctionPin5 = 20; //A1 Place holders ONLY
const int FunctionPin6 = 16; //A2 const int FunctionPin6 = 20; //A2 Place holders ONLY
const int FunctionPin7 = 17; //A3 const int FunctionPin7 = 18; //A5 Place holders ONLY
const int FunctionPin8 = 18; //A4 const int FunctionPin8 = 19; //A4 Place holders ONLY
const int FunctionPin9 = 19; //A5
const int AudioTriggerPin = 17; //A3 NOW USED AS Audio Trigger Pin INPUT_PULLUP
const int FunctionPin9 = 20; // Place holders ONLY
const int FunctionPin10 = 20; // Place holders ONLY const int FunctionPin10 = 20; // Place holders ONLY
const int FunctionPin11 = 20; const int FunctionPin11 = 20; // Place holders ONLY
const int FunctionPin12 = 20; const int FunctionPin12 = 20; // Place holders ONLY
const int FunctionPin13 = 20; const int FunctionPin13 = 20; // Place holders ONLY
const int FunctionPin14 = 20; const int FunctionPin14 = 20; // Place holders ONLY
const int FunctionPin15 = 20; const int FunctionPin15 = 20; // Place holders ONLY
const int FunctionPin16 = 20; const int FunctionPin16 = 20; // Place holders ONLY
int Function13_value = 0; int Function13_value = 0;
int Function14_value = 0; int Function14_value = 0;
@@ -227,7 +236,7 @@ void setup() //******************************************************
// Setup which External Interrupt, the Pin it's associated with that we're using // Setup which External Interrupt, the Pin it's associated with that we're using
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)
@@ -336,13 +345,27 @@ void loop() //****************************************************************
Dcc.process(); Dcc.process();
SoftwareServo::refresh(); SoftwareServo::refresh();
delay(2); delay(2);
#ifdef DEBUG
Serial.print("Motor1Speed= ");
Serial.println(Motor1Speed, DEC) ;
Serial.print("Motor2Speed= ");
Serial.println(Motor2Speed, DEC) ;
#endif
if (Motor1Speed != 0) { if (Motor1Speed != 0) {
if (Motor1ForwardDir == 0) gofwd1 (fwdtime, int((Motor1Speed&0x7f)*21)); if (Motor1ForwardDir == 0) gofwd1 (fwdtime, Motor1Speed<<4);
else gobwd1 (bwdtime, int((Motor1Speed&0x7f)*21)); else gobwd1 (bwdtime, Motor1Speed<<4);
}
else {
digitalWrite(m2h, LOW); //Motor1 OFF
digitalWrite(m2l, LOW); //Motor1 OFF
} }
if (Motor2Speed != 0) { if (Motor2Speed != 0) {
if (Motor2ForwardDir == 0) gofwd2 (fwdtime, int((Motor2Speed&0x7f)*21)); if (Motor2ForwardDir == 0) gofwd2 (fwdtime, Motor2Speed<<4);
else gobwd2 (bwdtime, int((Motor2Speed&0x7f)*21)); else gobwd2 (bwdtime, Motor2Speed<<4);
}
else {
digitalWrite(m0h, LOW); //Motor1 OFF
digitalWrite(m0l, LOW); //Motor1 OFF
} }
// //
for (int i=0; i < num_active_fpins; i++) { for (int i=0; i < num_active_fpins; i++) {
@@ -432,65 +455,78 @@ void loop() //****************************************************************
} }
void gofwd1(int fcnt,int fcycle) { void gofwd1(int fcnt,int fcycle) {
int icnt; int icnt;
int totcycle; int delta_tp,delta_tm;
delta_tp = fcycle+loopdelay<<2;
delta_tm = cyclewidth-fcycle-loopdelay;
icnt = 0; icnt = 0;
while (icnt < fcnt) while (icnt < fcnt)
{ {
digitalWrite(m2h, HIGH); //Motor1 digitalWrite(m2h, HIGH); //Motor1
delayMicroseconds(fcycle); delayMicroseconds(delta_tp);
digitalWrite(m2h, LOW); //Motor1 digitalWrite(m2h, LOW); //Motor1
delayMicroseconds(cyclewidth - fcycle); delayMicroseconds(delta_tm);
icnt++; icnt++;
} }
} }
void gobwd1(int bcnt,int bcycle) { void gobwd1(int bcnt,int bcycle) {
int icnt; int icnt;
int delta_tp,delta_tm;
delta_tp = bcycle+loopdelay<<2;
delta_tm = cyclewidth-bcycle-loopdelay;
icnt=0; icnt=0;
while (icnt < bcnt) while (icnt < bcnt)
{ {
digitalWrite(m2l, HIGH); //Motor1 digitalWrite(m2l, HIGH); //Motor1
delayMicroseconds(bcycle); delayMicroseconds(delta_tp);
digitalWrite(m2l, LOW); //Motor1 digitalWrite(m2l, LOW); //Motor1
delayMicroseconds(cyclewidth - bcycle); delayMicroseconds(delta_tm);
icnt++; icnt++;
} }
} }
void gofwd2(int fcnt,int fcycle) { void gofwd2(int fcnt,int fcycle) {
int icnt; int icnt;
int totcycle; int delta_tp,delta_tm;
delta_tp = fcycle+loopdelay<<2;
delta_tm = cyclewidth-fcycle-loopdelay;
icnt = 0; icnt = 0;
while (icnt < fcnt) while (icnt < fcnt)
{ {
digitalWrite(m0h, HIGH); //Motor2 digitalWrite(m0h, HIGH); //Motor2
delayMicroseconds(fcycle); delayMicroseconds(delta_tp);
digitalWrite(m0h, LOW); //Motor2 digitalWrite(m0h, LOW); //Motor2
delayMicroseconds(cyclewidth - fcycle); delayMicroseconds(delta_tm);
icnt++; icnt++;
} }
} }
void gobwd2(int bcnt,int bcycle) { void gobwd2(int bcnt,int bcycle) {
int icnt; int icnt;
int delta_tp,delta_tm;
delta_tp = bcycle+loopdelay<<2;
delta_tm = cyclewidth-bcycle-loopdelay;
icnt=0; icnt=0;
while (icnt < bcnt) while (icnt < bcnt)
{ {
digitalWrite(m0l, HIGH); //Motor2 digitalWrite(m0l, HIGH); //Motor2
delayMicroseconds(bcycle); delayMicroseconds(delta_tp);
digitalWrite(m0l, LOW); //Motor2 digitalWrite(m0l, LOW); //Motor2
delayMicroseconds(cyclewidth - bcycle); delayMicroseconds(delta_tm);
icnt++; icnt++;
} }
} }
void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION ForwardDir, DCC_SPEED_STEPS SpeedSteps ) { void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION ForwardDir, DCC_SPEED_STEPS SpeedSteps ) {
if (Function13_value==1) { if (Function13_value==1) {
Motor1Speed = Speed; Motor1Speed = (Speed & 0x7f );
if (Motor1Speed == 1) Motor1Speed=0;
Motor1ForwardDir = ForwardDir; Motor1ForwardDir = ForwardDir;
} }
if (Function14_value==1) { if (Function14_value==1) {
Motor2Speed = Speed; Motor2Speed = (Speed & 0x7f );
if (Motor2Speed == 1) Motor2Speed=0;
Motor2ForwardDir = ForwardDir; Motor2ForwardDir = ForwardDir;
} }
} }
void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) { void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) {
#ifdef DEBUG #ifdef DEBUG
Serial.print("Addr= "); Serial.print("Addr= ");

View File

@@ -1,5 +1,5 @@
// Production 17 Function DCC Decoder Dec_7Serv_10LED_6Ftn.ino // Production 17 Function DCC Decoder Dec_7Serv_10LED_6Ftn.ino
// Version 5.4 Geoff Bunza 2014,2015,2016 // Version 6.01 Geoff Bunza 2014,2015,2016
// NO LONGER REQUIRES modified software servo Lib // NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter // Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks // With sincere thanks
@@ -207,7 +207,7 @@ void setup() //******************************************************
// Setup which External Interrupt, the Pin it's associated with that we're using // Setup which External Interrupt, the Pin it's associated with that we're using
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 ); Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)

4
examples/SMA/Dec_Dir_and_Fade/Dec_Dir_and_Fade.ino Executable file → Normal file
View File

@@ -1,5 +1,5 @@
// Production 17 Function DCC Decoder Dec_Dir_and_Fade.ino // Production 17 Function DCC Decoder Dec_Dir_and_Fade.ino
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses // Now works with both short and long DCC Addesses
// LED control is dependent on direction of travel and Fade can be added // LED control is dependent on direction of travel and Fade can be added
@@ -110,7 +110,7 @@ void setup()
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up // Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
} }
void loop() void loop()
{ {

View File

@@ -1,5 +1,5 @@
// Production 17 Function DCC Decoder Dec_SMA12_LED_Groups.ino // Production 17 Function DCC Decoder Dec_SMA12_LED_Groups.ino
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses // Now works with both short and long DCC Addesses
// NO LONGER REQUIRES modified software servo Lib // NO LONGER REQUIRES modified software servo Lib
@@ -127,7 +127,7 @@ void setup()
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up // Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET ) if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )

View File

@@ -1,5 +1,5 @@
// Production Stepper Drive DCC Decoder Dec_Stepper_6Ftn.ino // Production Stepper Drive DCC Decoder Dec_Stepper_6Ftn.ino
// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 // Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
// Now works with both short and long DCC Addesses // Now works with both short and long DCC Addesses
// NO LONGER REQUIRES modified software servo Lib // NO LONGER REQUIRES modified software servo Lib
@@ -236,7 +236,7 @@ void setup() //******************************************************
// Setup which External Interrupt, the Pin it's associated with that we're using // Setup which External Interrupt, the Pin it's associated with that we're using
Dcc.pin(0, 2, 0); Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver // Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
delay(800); delay(800);
#if defined(DECODER_LOADED) #if defined(DECODER_LOADED)

View File

@@ -1,9 +1,9 @@
name=NmraDcc name=NmraDcc
version=2.0.0 version=2.0.1
author=Alex Shepherd, Wolfgang Kuffer, Geoff Bunza, Martin Pischky, Franz-Peter Müller, Sven (littleyoda) author=Alex Shepherd, Wolfgang Kuffer, Geoff Bunza, Martin Pischky, Franz-Peter Müller, Sven (littleyoda), Hans Tanner
maintainer=Alex Shepherd <kiwi64ajs@gmail.com> maintainer=Alex Shepherd <kiwi64ajs@gmail.com>
sentence=Enables NMRA DCC Communication sentence=Enables NMRA DCC Communication
paragraph=This library allows you to interface to a NMRA DCC track signal and receive DCC commands. The library currently supports the AVR ATTiny84/85 & ATMega88/168/328/32u4 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. WARNING as of version 1.4.4 support for the call-back functions notifyDccAccState() and notifyDccSigState() has been removed, please check and update your sketches, as they will silently fail. 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.
category=Communication category=Communication
url=https://github.com/mrrwa/NmraDcc url=https://github.com/mrrwa/NmraDcc
architectures=avr,esp8266,STM32F1 architectures=*