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
|
|
Directly connected to the track |
|
|
Very low cost |
|
|
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