Train Modeling Digital Devices Control (DCC)

Need someone to correct all my grammatical error, please.

History

        This is the second part of the DCC project, controlling all accessories via the DCC data on the track.  You can connect: switches, lights and many more...  This board has hardware address setting via jumpers, so you can have many of those

 

Features

puce Directly connected to the track
puce Very low cost
puce 8 relay output

 

Pictures

DCC accessory controller

 

Sources codes & Schematics

-Schematic DCC Accessory Control in PDF format

 

//**************************************
// DCC Accessory
// Version 1.0 Dec 2003
// Sylvain Bissonnette
//
// Note : Serial port is ONLY use for
//         debug purpose.
//**************************************
//
//    Return Stack must be 16
//          Xtal 8Mhz
//
//**************************************
//            I N C L U D E
//**************************************
#include <io2313v.h>
#include <macros.h>

//**************************************
//            D E F I N E
//**************************************
#define TRUE       0x01
#define  FALSE     0x00

//#define DEBUG
#define VERBOS

//**************************************
//          P R O T O T Y P E
//**************************************
void main(void);
void _StackOverflowed(char c);
void TxString(const char *ptr);
void TxChar(unsigned char ch);
void InputCapture(void);
void DegugPacket(void);

//**************************************
//   G L O B A L   V A R I A B L E
//**************************************
unsigned Message1,Message2;
unsigned char NewMessage = FALSE;
unsigned char Address = 128;
unsigned char Accessory[8];

//**************************************
//            M A I N
//**************************************
void main(void)
{
unsigned char i;
unsigned char Output;
unsigned char Stat;

WDR();
WDTCR = 0x0e;        // Enable WatchDog at 0.97 sec

UBRR = 8;            //set baud rate 38400
UCR  = 0x18;         //enable
DDRD = 0x02;         // PD1 TX pin as output all other is input
PORTD = 0x3d;        // PD5,4,3,2,0 as internal pull up

#ifdef VERBOS
TxString("\n\rRestart\n\r\0");
TxString("DCC Accessory V:1.0\n\r\0");
#endif

//Timer1
TCCR1B = 0x82;       // Timer1 / 8 & Input Capture on Rising eadge, noise canceller on
TIMSK = 0x08;        // int enable on Timer 1 Input Capture

//Port B
DDRB = 0xff;         // all port B is in output

for (i=0;i<8;i++) Accessory[i] = FALSE;
PORTB = 0x00;

SEI();
while(1)
      {
      _StackCheck();
      WDR();
      Address = ((PIND >> 2) & 0x0f) + 128;
      if (NewMessage == TRUE)
         {
         NewMessage = FALSE;

         if ((Message1 == ((Address>>4) | 0x80)) && ((Message2 & 0xf0) == ((Address<<4) & 0xf0)))
              {
           Output = (Message2 & 0x07);
           Stat = ((Message2>>3)&0x01);

           if (Accessory[Output] != Stat)
             {
             Accessory[Output] = Stat;

             if ((Output == 0x00) && (Stat))
               {
               #ifdef VERBOS
               TxString("00->ON\n\r\0");
               #endif
               PORTB |= 0x01;
               }
             if ((Output == 0x00) && !(Stat))
               {
               #ifdef VERBOS
               TxString("00->OFF\n\r\0");
               #endif
               PORTB &= ~0x01;
               }
             if ((Output == 0x01) && (Stat))
               {
               #ifdef VERBOS
               TxString("01->ON\n\r\0");
               #endif
               PORTB |= 0x02;
               }
             if ((Output == 0x01) && !(Stat))
               {
               #ifdef VERBOS
               TxString("01->OFF\n\r\0");
               #endif
               PORTB &= ~0x02;
               }
             if ((Output == 0x02) && (Stat))
               {
               #ifdef VERBOS
               TxString("02->ON\n\r\0");
               #endif
               PORTB |= 0x04;
               }
             if ((Output == 0x02) && !(Stat))
               {
               #ifdef VERBOS
               TxString("02->OFF\n\r\0");
               #endif
               PORTB &= ~0x04;
               }
             if ((Output == 0x03) && (Stat))
               {
               #ifdef VERBOS
               TxString("03->ON\n\r\0");
               #endif
               PORTB |= 0x08;
               }
             if ((Output == 0x03) && !(Stat))
               {
               #ifdef VERBOS
               TxString("03->OFF\n\r\0");
               #endif
               PORTB &= ~0x08;
               }
             if ((Output == 0x04) && (Stat))
               {
               #ifdef VERBOS
               TxString("04->ON\n\r\0");
               #endif
               PORTB |= 0x10;
               }
             if ((Output == 0x04) && !(Stat))
               {
               #ifdef VERBOS
               TxString("04->OFF\n\r\0");
               #endif
               PORTB &= ~0x10;
               }
             if ((Output == 0x05) && (Stat))
               {
               #ifdef VERBOS
               TxString("05->ON\n\r\0");
               #endif
               PORTB |= 0x20;
               }
             if ((Output == 0x05) && !(Stat))
               {
               #ifdef VERBOS
               TxString("05->OFF\n\r\0");
               #endif
               PORTB &= ~0x20;
               }
             if ((Output == 0x06) && (Stat))
               {
               #ifdef VERBOS
               TxString("06->ON\n\r\0");
               #endif
               PORTB |= 0x40;
               }
             if ((Output == 0x06) && !(Stat))
               {
               #ifdef VERBOS
               TxString("06->OFF\n\r\0");
               #endif
               PORTB &= ~0x40;
               }
             if ((Output == 0x07) && (Stat))
               {
               #ifdef VERBOS
               TxString("07->ON\n\r\0");
               #endif
               PORTB |= 0x80;
               }
             if ((Output == 0x07) && !(Stat))
               {
               #ifdef VERBOS
               TxString("07->OFF\n\r\0");
               #endif
               PORTB &= ~0x80;
               }
             }
           }
         }
      }
}

/**********************************************************

Name:       void _StackOverflowed(char c)

Description:   This function is automaticaly called if
            the stack crash.
           

Input:         none

Output:        PB7

Misc:      
**********************************************************/
void _StackOverflowed(char c)
   {
   TxString("\n\rStack CRASH!@#$\n\r");
   while(1);
   }

/**********************************************************

Name:       void TxString(unsigned  *char)

Description:   Send a char serial port

Input:         char

Output:        none

Misc:

**********************************************************/
void TxString(const char *ptr)
{
while (*ptr != 0x00) TxChar(*ptr++);
}

/**********************************************************

Name:       void TxChar(unsigned char)

Description:   Send a char serial port

Input:         char

Output:        none

Misc:

**********************************************************/
void TxChar(unsigned char ch)
{
while ((USR & 0x20) != 0x20) WDR(); // Wait for empty transmit buffer
UDR = ch;                          // Write char
}

/**********************************************************

Name:       void InputCaptre(void)

Description:   This function is call each time the DCC
            Bit have a rising edge (or falling depending
            of the config). 

Input:         none    

Output:       

Misc:      

**********************************************************/
#pragma interrupt_handler InputCapture:4
void InputCapture(void)
{
static unsigned int LastCapture;
static unsigned int PulseWidth;
static unsigned char Pre = 0;
static unsigned char BitPtr = 0;
static unsigned long Message = 0;
static unsigned char Byte1,Byte2,Byte3;
static unsigned char CRC = 0;

PulseWidth = ICR1 - LastCapture;
LastCapture = ICR1;
if (PulseWidth < 150) // 150 us    
   {
   // this is a 1
   Pre++;                // Add 1 to prembule variable
   Message = Message << 1;  // Add the 1 to the message string
   Message |= 0x00000001;
   }
else
   {
   // this is a 0
   if (Pre > 10)         // If we received a 0 after more than 10 1 it's
        {                      // the start bit after the preambule
     Message = 0;
     BitPtr = 0;
     }
   Pre = 0;                 // Clear Pre for next message
   Message = Message << 1;  // Add the 0 to the message string
   }
BitPtr++;                // Bit count plus one

if (BitPtr > 26)         // if we have more then 26 bit the message is
   {                     // Complete
   BitPtr = 0;

   Byte1 = Message >> 18;   // Extract the 2 data byte from the message
   Byte2 = Message >> 9;
   Byte3 = Message;         // Extract the Xor from the message

   if ((Byte1 ^ Byte2) == Byte3)
        {
     CRC = 0;               // Message byte is good
     Message1 = Byte1;      // Give the data byte 1 to the application
     Message2 = Byte2;      // Give the data byte 2 to the application
     NewMessage = TRUE;  // Notify new message to the application
     }
   else
      {
     CRC++;
     if (CRC > 3) // More than 3 CONSECUTIVE CRC error: inverse capture edge 
       {
       TCCR1B ^= 0x40;
       CRC = 0;
       }
     }
   #ifdef DEBUG
   DegugPacket();
   #endif
   }
}

/**********************************************************

Name:       void DegugPacket(void)

Description:  

Input:         none    

Output:       

Misc:      

**********************************************************/
#ifdef DEBUG
void DegugPacket(void)
{
unsigned char i;

for (i=32;i!=0;i--)
      {
   if ((Message >> i) & 0x00000001) TxChar('1');
   else TxChar('0');
   }
TxString("\n\r\0");
for (i=7;i!=0;i--)
   {
   if ((Message1 >> i) & 0x01) TxChar('1');
   else TxChar('0');
   }
TxString("\n\r\0");
for (i=7;i!=0;i--)
   {
   if ((Message2 >> i) & 0x01) TxChar('1');
   else TxChar('0');
   }
TxString("\n\r\0");
TxString("\n\r\0");
}
#endif