-
Notifications
You must be signed in to change notification settings - Fork 1
/
DDCHardware_config.h
172 lines (153 loc) · 7.45 KB
/
DDCHardware_config.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/****************************************************************************
* Copyright (C) 2016-2022 Philipp Gahtow
*
* DCC Waveform Timer Configuration
*
* DCC Master Interface can generate DCC Signal
* either with Timer1 (16-bit) or with Timer2 (8-bit) by default!
* for ARM on Arduino DUE with TC3 = Timer4 (TC1 Channel 0)
* for ESP8266 with Timer1
* for ESP32 with Timer1
****************************************************************************/
#define PREAMBLE_LENGTH 16 //1's for the preamble (NMRA mind. 10x, normal: 12x plus RailCom cutout)
#define ADD_LONG_PREAMBLE_LENGTH 8 //additional length for Service Mode Packet
#define RAILCOM_CUTOUT_LENGTH 4 //length the preamble will be cut out when railcom data will transmit
//--------------------------------------------------------------------------------------
/*
NEM 670 – Ausgabe 2013:
Dauer des Teil-Einsbits: t = 58 µs & zulässige Toleranzen +/- 3 µs am Gleis
Dauer des Teil-Nullbits: t ≥ 100 µs, normal: 116µs
*/
/******************************************/
#if defined(__AVR__)
//CONTROL What Timer we should use:
//#define DCC_USE_TIMER1 //USE 16-bit TIMER1
#undef DCC_USE_TIMER1 //USE 8-bit TIMER2
#endif
/******************************************/
//DCC truth table:
//OFF:
#if defined(__AVR__)
#define DCC_OUTPUT1_OFF() {*d1reg &= ~d1bit;} //LOW
#endif
#define DCC_OUTPUT1_OFF_legacy LOW
#if defined(__AVR__)
#define DCC_OUTPUT2_OFF() {*d2reg &= ~d2bit;} //LOW
#endif
#define DCC_OUTPUT2_OFF_legacy LOW
//RailCom:
#if defined(__AVR__)
#define DCC_OUTPUT1_RC() {*d1reg &= ~d1bit;} //LOW
#endif
#define DCC_OUTPUT1_RC_legacy LOW
#if defined(__AVR__)
#define DCC_OUTPUT2_RC() {*d2reg &= ~d2bit;} //LOW
#endif
#define DCC_OUTPUT2_RC_legacy LOW
//DCC LOW:
#if defined(__AVR__)
#define DCC_OUTPUT1_LOW() {*d1reg &= ~d1bit;} //LOW
#endif
#define DCC_OUTPUT1_LOW_legacy LOW
#if defined(__AVR__)
#define DCC_OUTPUT2_LOW() {*d2reg |= d2bit;} //HIGH
#endif
#define DCC_OUTPUT2_LOW_legacy HIGH
//DCC HIGH:
#if defined(__AVR__)
#define DCC_OUTPUT1_HIGH() {*d1reg |= d1bit;} //HIGH
#endif
#define DCC_OUTPUT1_HIGH_legacy HIGH
#if defined(__AVR__)
#define DCC_OUTPUT2_HIGH() {*d2reg &= ~d2bit;} //LOW
#endif
#define DCC_OUTPUT2_HIGH_legacy LOW
/******************************************/
//Arduino DUE DCC Signal generation on TC3 = Timer4 (TC1 Channel 0)
#if defined(__SAM3X8E__)
#define half_one_count 305 //29usec pulse
#define one_count 609 // Calls every 58µs
#define zero_high_count 1050 // Calls every 100µs
//#define zero_low_count 1050 // Calls every 100µs
#define DCC_ARM_TC_TIMER TC2 //Timer
#define DCC_ARM_TC_CHANNEL 0 //Channel
#define DCC_ARM_MATCH_INT TC6_IRQn //Interrupt that will be used
#define DCC_ARM_TC_SIGNAL TC6_Handler() //Interrupt Handler
#define DCC_TMR_OUTP_ONE_HALF() {TC_SetRC(DCC_ARM_TC_TIMER, DCC_ARM_TC_CHANNEL, half_one_count); }
#define DCC_TMR_OUTP_ONE_COUNT() {TC_SetRC(DCC_ARM_TC_TIMER, DCC_ARM_TC_CHANNEL, one_count); }
#define DCC_TMR_OUTP_ZERO_HIGH() {TC_SetRC(DCC_ARM_TC_TIMER, DCC_ARM_TC_CHANNEL, zero_high_count);}
//#define DCC_TMR_OUTP_ZERO_LOW() {TC_SetRC(DCC_ARM_TC_TIMER, DCC_ARM_TC_CHANNEL, zero_low_count);}
/******************************************/
//ESP8266 DCC Signal generation with Timer1
#elif defined(ESP8266)
//TIM_DIV1 = 0 -> 80MHz (80 ticks/us - 104857.588us max)
//TIM_DIV16 = 1 -> 5MHz (5 ticks/us - 1677721.4us max)
//TIM_DIV256 = 3 -> 312.5Khz (1 tick = 3.2us - 26843542.4us max)
#define half_one_count 2080 // 145 //29usec pulse old:2280 new:2080
#define one_count 4160 // 290 - Calls every 58µs old:4580 new:4160
#define zero_high_count 7920 // 500 - Calls every 100µs
#define zero_low_count 7920 // 500 // Calls every 100µs
#define DCC_ESP_TIMER_DIV TIM_DIV1
#define DCC_ESP_TIMER_SET TIM_EDGE
#define DCC_ESP_TIMER_LOOP TIM_SINGLE
#define DCC_TMR_OUTP_ONE_HALF() {timer1_write(half_one_count); last_timer = half_one_count;}
#define DCC_TMR_OUTP_ONE_COUNT() {timer1_write(one_count); last_timer = one_count;}
#define DCC_TMR_OUTP_ZERO_HIGH() {timer1_write(zero_high_count); last_timer = zero_high_count;}
#define DCC_TMR_OUTP_ZERO_LOW() {timer1_write(zero_low_count); last_timer = zero_low_count;}
/******************************************/
//ESP32 DCC Signal generation with Timer1
#elif defined(ESP32)
#define half_one_count 580 //29usec pulse
#define one_count 960 // Calls every 58µs
#define zero_high_count 2001 // Calls every 100µs
#define zero_low_count 2001 // Calls every 100µs
#define DCC_ESP_TIMER_ID 1 //the Timer number from 0 to 3
#define DCC_ESP_TIMER_PRESCALE 4 //prescale the value of the time divider
#define DCC_ESP_TIMER_FLAG true //flag true to count on the rising edge, false to count on the falling edge
#define DCC_TMR_OUTP_ONE_HALF() {timerAlarmWrite(timer, half_one_count, true); last_timer = half_one_count;}
#define DCC_TMR_OUTP_ONE_COUNT() {timerAlarmWrite(timer, one_count, true); last_timer = one_count;}
#define DCC_TMR_OUTP_ZERO_HIGH() {timerAlarmWrite(timer, zero_high_count, true); last_timer = zero_high_count;}
#define DCC_TMR_OUTP_ZERO_LOW() {timerAlarmWrite(timer, zero_low_count, true); last_timer = zero_low_count;}
/******************************************/
//USE the Timer1 for the DCC Signal generation on AVR
#elif defined(DCC_USE_TIMER1)
#undef DCC_USE_TIMER2
#define half_one_count 57 //29usec pulse
#define one_count 115 //58us = 115
#define zero_high_count 199 //100us = 199 !old: 116us = 228
#define zero_low_count 199 //100us
#define DCC_TMR_SIGNAL TIMER1_COMPA_vect
#define DCC_INIT_COMPARATOR TCCR1A
#define DCC_TMR_CONTROL_REG TCCR1B
//turn on CTC mode in WGM12 and set CS11 for 8 prescaler in TCCR1B
#define DCC_TMR_CONTROL_SET() {DCC_TMR_CONTROL_REG = 1 << WGM12 | 1 << CS11;}
#define DCC_TMR_COUNT_REG TCNT1
#define DCC_TMR_MATCH_INT() {TIMSK1 |= (1 << OCIE1A);} //Compare Match Interrupt Enable
#define DCC_TMR_OUTP_CAPT_REG OCR1A
#define DCC_TMR_OUTP_ONE_HALF() {OCR1A = OCR1B = half_one_count;}
#define DCC_TMR_OUTP_ONE_COUNT() {OCR1A = OCR1B = one_count;}
#define DCC_TMR_OUTP_ZERO_HIGH() {OCR1A = OCR1B = zero_high_count;}
#define DCC_TMR_OUTP_ZERO_LOW() {OCR1A = OCR1B = zero_low_count;}
/******************************************/
//USE the Timer2 for the DCC Signal generation on AVR
#else
#define DCC_USE_TIMER2
#define half_one_count 198 //29usec pulse
#define one_count 141 //58usec pulse length = 141 = 0x8D
#define zero_high_count 56 //100us = 56 !old: 116us = 0x1B (27) pulse length
#define zero_low_count 56 //100us
#define DCC_TMR_SIGNAL TIMER2_OVF_vect
#define DCC_INIT_COMPARATOR TCCR2A
#define DCC_TMR_CONTROL_REG TCCR2B
//Timer2 Settings: Timer Prescaler /8, mode 0
//Timmer clock = 16MHz/8 = 2MHz oder 0,5usec
#define DCC_TMR_CONTROL_SET() {DCC_TMR_CONTROL_REG = 0 << CS22 | 1 << CS21 | 0 << CS20;}
#define DCC_TMR_COUNT_REG TCNT2
#define DCC_TMR_MATCH_INT() {TIMSK2 = 1 << TOIE2;} //Overflow Interrupt Enable
//note that there is a latency so take the last time of Timer2 also:
#define DCC_TMR_OUTP_ONE_HALF() {DCC_TMR_COUNT_REG = DCC_TMR_COUNT_REG + half_one_count; last_timer = half_one_count;}
#define DCC_TMR_OUTP_ONE_COUNT() {DCC_TMR_COUNT_REG = DCC_TMR_COUNT_REG + one_count; last_timer = one_count;}
#define DCC_TMR_OUTP_ZERO_HIGH() {DCC_TMR_COUNT_REG = DCC_TMR_COUNT_REG + zero_high_count; last_timer = zero_high_count;}
#define DCC_TMR_OUTP_ZERO_LOW() {DCC_TMR_COUNT_REG = DCC_TMR_COUNT_REG + zero_low_count; last_timer = zero_low_count;}
/******************************************/
#endif