Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
Loco.cxx
Go to the documentation of this file.
1
35#include "dcc/Loco.hxx"
36
37#include "utils/logging.h"
38#include "dcc/UpdateLoop.hxx"
39
40namespace dcc
41{
42
46extern void createtrains();
47
48template <> DccTrain<Dcc28Payload>::~DccTrain()
49{
50 packet_processor_remove_refresh_source(this);
51}
52
53template <> DccTrain<Dcc128Payload>::~DccTrain()
54{
55 packet_processor_remove_refresh_source(this);
56}
57
58unsigned DccPayloadBase::get_fn_update_code(unsigned address)
59{
60 if (address < 5)
61 {
62 return FUNCTION0;
63 }
64 else if (address < 9)
65 {
66 return FUNCTION5;
67 }
68 else if (address < 13)
69 {
70 return FUNCTION9;
71 }
72 else if (address <= 68)
73 {
74 return FUNCTION13 + (address - 13) / 8;
75 }
76 return SPEED;
77}
78
79// Generates next outgoing packet.
80template <class Payload>
81void DccTrain<Payload>::get_next_packet(unsigned code, Packet *packet)
82{
83 packet->start_dcc_packet();
84 if (this->p.isShortAddress_)
85 {
86 packet->add_dcc_address(DccShortAddress(this->p.address_));
87 }
88 else
89 {
90 packet->add_dcc_address(DccLongAddress(this->p.address_));
91 }
92 if (code == REFRESH)
93 {
94 code = MIN_REFRESH + this->p.nextRefresh_++;
95 if (this->p.nextRefresh_ > MAX_REFRESH - MIN_REFRESH)
96 {
97 this->p.nextRefresh_ = 0;
98 }
99 }
100 else
101 {
102 // User action. Up repeat count.
103 packet->packet_header.rept_count = 2;
104 }
105 switch (code)
106 {
107 case FUNCTION0:
108 {
109 packet->add_dcc_function0_4(
110 (this->p.fn_ & 0x1E) | this->get_effective_f0());
111 return;
112 }
113 case FUNCTION5:
114 {
115 packet->add_dcc_function5_8(this->p.fn_ >> 5);
116 return;
117 }
118 case FUNCTION9:
119 {
120 packet->add_dcc_function9_12(this->p.fn_ >> 9);
121 return;
122 }
123 case FUNCTION13:
124 {
125 packet->add_dcc_function13_20(this->p.fn_ >> 13);
126 return;
127 }
128 case FUNCTION21:
129 {
130 packet->add_dcc_function21_28(this->p.fn_ >> 21);
131 return;
132 }
133 case FUNCTION29:
134 case FUNCTION37:
135 case FUNCTION45:
136 case FUNCTION53:
137 case FUNCTION61:
138 {
139 unsigned s = code - FUNCTION29;
140 packet->add_dcc_function_hi(29 + s * 8, this->p.fhi_[s]);
141 return;
142 }
143 case ESTOP:
144 {
145 this->p.add_dcc_estop_to_packet(packet);
146 packet->packet_header.rept_count = 3;
147 return;
148 }
149 default:
150 LOG(WARNING, "Unknown packet generation code: %x", code);
151 // fall through
152 case SPEED:
153 {
154 if (this->p.directionChanged_)
155 {
156 // packet->packet_header.rept_count = 2;
157 this->p.directionChanged_ = 0;
158 }
159 // packet->packet_header.rept_count = 1;
160 this->p.add_dcc_speed_to_packet(packet);
161 return;
162 }
163 }
164}
165
167{
168 p.address_ = a.value;
169 packet_processor_add_refresh_source(this);
170}
171
172MMOldTrain::~MMOldTrain()
173{
174 packet_processor_remove_refresh_source(this);
175}
176
177// Generates next outgoing packet.
178void MMOldTrain::get_next_packet(unsigned code, Packet *packet)
179{
180 packet->start_mm_packet();
182
183 if (code == ESTOP)
184 {
185 packet->add_mm_speed(
186 Packet::EMERGENCY_STOP); // will change the direction.
189 }
190 else if (p.directionChanged_)
191 {
194 }
195 else
196 {
197 packet->add_mm_speed(p.speed_);
198 if (code != REFRESH)
199 {
200 packet->packet_header.rept_count = 2;
201 }
202 }
203}
204
206{
207 p.address_ = a.value;
208 packet_processor_add_refresh_source(this);
209}
210
211MMNewTrain::~MMNewTrain()
212{
213 packet_processor_remove_refresh_source(this);
214}
215
216// Generates next outgoing packet.
217void MMNewTrain::get_next_packet(unsigned code, Packet *packet)
218{
219 packet->start_mm_packet();
221
222 if (code == REFRESH)
223 {
224 unsigned r = p.nextRefresh_;
225 if ((r & 1) == 0) {
226 code = SPEED;
227 } else {
228 // TODO(bracz): check if this refresh cycle confuses the marklin
229 // engines' directional state.
230 r >>= 1;
231 r += MM_F1;
232 code = r;
233 }
234 if (p.nextRefresh_ == MM_MAX_REFRESH) {
235 p.nextRefresh_ = 0;
236 } else {
237 ++p.nextRefresh_;
238 }
239 }
240 else
241 {
242 packet->packet_header.rept_count = 2;
243 }
244 if (code == ESTOP)
245 {
246 packet->add_mm_new_speed(
247 !p.direction_,
248 Packet::EMERGENCY_STOP); // will change the direction.
251 }
252 else if (code == SPEED)
253 {
255 {
258 p.nextRefresh_ = 0; // sends another speed packet
259 packet->mm_shift();
260 }
261 else
262 {
264 packet->mm_shift();
265 }
266 }
267 else if (MM_F1 <= code && code <= MM_F4)
268 {
269 unsigned fnum = code + 1 - MM_F1;
270 packet->add_mm_new_fn(fnum, p.fn_ & (1 << fnum), p.speed_);
271 //packet->mm_shift();
272 //packet->add_mm_new_speed(!p.direction_, p.speed_);
273 }
274}
275
277 Dcc28Train train1(DccShortAddress(1));
278 Dcc128Train train2(DccShortAddress(1));
279 MMNewTrain train3(MMAddress(1));
280 MMOldTrain train4(MMAddress(1));
281}
282
283} // namespace dcc
void createtrains()
Forces compilation of all existing train implementations even though many are actually templates.
Definition Loco.cxx:276
@ MAX_REFRESH
@TODO(balazs.racz) choose adaptive max-refresh based on how many functions are actually in use for th...
Definition Loco.hxx:85
MMOldPayload p
Payload – actual data we know about the train.
Definition Loco.hxx:351
TrainImpl class for a DCC locomotive.
Definition Loco.hxx:493
void get_next_packet(unsigned code, Packet *packet) OVERRIDE
Generates next outgoing packet.
Definition Loco.cxx:81
TrainImpl structure for Marklin-Motorola v2 protocol locomotives.
Definition Loco.hxx:747
MMNewTrain(MMAddress a)
Constructor.
Definition Loco.cxx:205
void get_next_packet(unsigned code, Packet *packet) OVERRIDE
Generates next outgoing packet.
Definition Loco.cxx:217
TrainImpl structure for Marklin-Motorola v1 protocol locomotives.
Definition Loco.hxx:639
MMOldTrain(MMAddress a)
Constructor.
Definition Loco.cxx:166
void get_next_packet(unsigned code, Packet *packet) OVERRIDE
Generates next outgoing packet.
Definition Loco.cxx:178
#define LOG(level, message...)
Conditionally write a message to the logging output.
Definition logging.h:99
static const int WARNING
Loglevel that is always printed, reporting a warning or a retryable error.
Definition logging.h:55
uint8_t rept_count
The packet will be sent 1 + rept_count times to the wire.
Definition packet.h:74
Strongly typed wrapper representing a long DCC address.
Definition Address.hxx:66
static unsigned get_fn_update_code(unsigned address)
Definition Loco.cxx:58
Strongly typed wrapper representing a short DCC address.
Definition Address.hxx:49
Strongly typed wrapper representing a marklin-motorola protocol address.
Definition Address.hxx:82
uint8_t value
Address value.
Definition Address.hxx:86
unsigned nextRefresh_
internal refresh cycle state machine
Definition Loco.hxx:675
unsigned speed_
Speed step we last set.
Definition Loco.hxx:673
unsigned direction_
0: forward, 1: reverse
Definition Loco.hxx:667
unsigned directionChanged_
Whether the direction change packet still needs to go out.
Definition Loco.hxx:669
unsigned address_
largest address allowed is 80, but we keep a few more bits around to allow for an extension to arbitr...
Definition Loco.hxx:661
unsigned fn_
function f0-f4.
Definition Loco.hxx:665
unsigned address_
largest address allowed is 80, but we keep a few more bits around to allow for an extension to arbitr...
Definition Loco.hxx:564
unsigned directionChanged_
Whether the direction change packet still needs to go out.
Definition Loco.hxx:572
unsigned speed_
Speed step we last set.
Definition Loco.hxx:574
unsigned direction_
0: forward, 1: reverse
Definition Loco.hxx:570
Represents a command to be sent to the track driver.
Definition Packet.hxx:52
void start_mm_packet()
Sets the packet type to marklin-motorola.
Definition Packet.cxx:400
void add_mm_new_speed(bool is_fwd, unsigned speed)
Sets the packet to a direction-aware 14-step MM speed-and-light packet.
Definition Packet.cxx:474
static const unsigned EMERGENCY_STOP
Send this speed step to emergency-stop the locomotive.
Definition Packet.hxx:56
void add_dcc_function21_28(unsigned values)
Adds a DCC function group command to the packet.
Definition Packet.hxx:200
void add_mm_speed(unsigned speed)
Sets the packet to a 14-step MM speed-and-light packet.
Definition Packet.cxx:456
void add_dcc_function_hi(uint8_t base, uint8_t values)
Adds a DCC function group command to the packet.
Definition Packet.cxx:220
void add_dcc_function0_4(unsigned values)
Adds a DCC function group command to the packet.
Definition Packet.cxx:194
void add_dcc_function5_8(unsigned values)
Adds a DCC function group command to the packet.
Definition Packet.cxx:204
void add_mm_new_fn(unsigned fn_num, bool value, unsigned speed)
Creates a speed-and-fn packet for the new MM format.
Definition Packet.cxx:500
void start_dcc_packet()
Initializes the packet structure for a regular DCC packet.
Definition Packet.hxx:99
static const unsigned CHANGE_DIR
Send this speed step to switch direction of the locomotive.
Definition Packet.hxx:59
void add_dcc_address(DccShortAddress address)
Adds the header to the packet needed for addressing a DCC locomotive.
Definition Packet.cxx:98
void add_mm_address(MMAddress address, bool light)
Sets the address and F0 bits of an MM packet to a specific loco address.
Definition Packet.cxx:417
void add_dcc_function13_20(unsigned values)
Adds a DCC function group command to the packet.
Definition Packet.hxx:193
void mm_shift()
Shifts a MM packet to the second half of the packet buffer.
Definition Packet.cxx:534
void add_dcc_function9_12(unsigned values)
Adds a DCC function group command to the packet.
Definition Packet.cxx:212