118 if (
p.lastSetSpeed_ == new_speed)
120 LOG(
VERBOSE,
"not updating speed: old speed %04x, new speed %04x",
121 p.lastSetSpeed_, new_speed);
124 p.lastSetSpeed_ = new_speed;
127 if (speed.direction() !=
p.direction_)
129 p.directionChanged_ = 1;
130 p.direction_ = speed.direction();
133 float f_speed = speed.mph();
136 f_speed *= ((
p.get_speed_steps() * 1.0) / 126);
137 unsigned sp = f_speed + 0.5;
142 if (sp >
p.get_speed_steps())
144 sp =
p.get_speed_steps();
154 if (previous_light && !light)
157 packet_processor_notify_update(
this,
p.get_fn_update_code(0));
159 packet_processor_notify_update(
this, SPEED);
160 if (light && !previous_light)
163 packet_processor_notify_update(
this,
p.get_fn_update_code(0));
186 dir0.set_direction(
p.direction_);
188 p.directionChanged_ = 1;
192 packet_processor_notify_update(
this, ESTOP);
203 const uint32_t virtf0 = config_dcc_virtual_f0_offset();
204 if (address == 0 &&
p.f0SetDirectional_)
206 if (
p.direction_ == 0)
208 p.f0OnForward_ = value ? 1 : 0;
212 p.f0OnReverse_ = value ? 1 : 0;
220 p.f0SetDirectional_ = 1;
223 if (
p.direction_ == 0)
225 p.f0OnForward_ =
p.get_fn_store(0);
230 p.f0OnReverse_ =
p.get_fn_store(0);
236 p.f0SetDirectional_ = 0;
246 p.f0BlankForward_ = value ? 1 : 0;
247 packet_processor_notify_update(
this,
p.get_fn_update_code(0));
252 p.f0BlankReverse_ = value ? 1 : 0;
253 packet_processor_notify_update(
this,
p.get_fn_update_code(0));
256 if (address >
p.get_max_fn())
261 p.set_fn_store(address, value);
262 packet_processor_notify_update(
this,
p.get_fn_update_code(address));
268 const uint32_t virtf0 = config_dcc_virtual_f0_offset();
271 return p.f0SetDirectional_;
275 return p.f0BlankForward_;
279 return p.f0BlankReverse_;
281 if (address >
p.get_max_fn())
286 return p.get_fn_store(address) ? 1 : 0;
296 return p.get_address_type();
319 unsigned is_on =
p.f0SetDirectional_ == 0 ? (
p.fn_ & 1)
320 :
p.direction_ == 0 ?
p.f0OnForward_
322 if (
p.direction_ == 0 &&
p.f0BlankForward_)
326 if (
p.direction_ == 1 &&
p.f0BlankReverse_)
336 if (
p.f0SetDirectional_)
339 if (
p.direction_ == 0 &&
p.f0OnForward_)
343 if (
p.direction_ == 1 &&
p.f0OnReverse_)
423 fhi_[idx / 8] |= (1u << (idx & 7));
427 fhi_[idx / 8] &= ~(1u << (idx & 7));
439 return (
fn_ & (1u << idx)) != 0;
444 return (
fhi_[idx / 8] & (1u << (idx & 7))) != 0;
456 : TrainAddressType::DCC_LONG_ADDRESS;
465 memset(
this, 0,
sizeof(*
this));
489static_assert(
sizeof(Dcc28Payload) == 16,
"size of dcc payload is wrong");
498 this->
p.isShortAddress_ = 1;
499 this->
p.address_ = a.
value;
500 packet_processor_add_refresh_source(
this);
506 this->
p.isShortAddress_ = 0;
507 this->
p.address_ = a.
value;
508 packet_processor_add_refresh_source(
this);
527 memset(
this, 0,
sizeof(*
this));
560 memset(
this, 0,
sizeof(*
this));
620 return (
fn_ & (1u << idx)) != 0;
633 return TrainAddressType::MM;
657 memset(
this, 0,
sizeof(*
this));
721 return (
fn_ & (1u << idx)) != 0;
728 if (1 <= address && address <= 4)
730 return MM_F1 + address - 1;
741 return TrainAddressType::MM;
DccTrainUpdateCode
Describes what sort of packet the dcc:PacketSource (usually a single train) should generate.
@ MAX_REFRESH
@TODO(balazs.racz) choose adaptive max-refresh based on how many functions are actually in use for th...
uint16_t float16_t
This type represents how velocity is seen on the wire (16 bit float).
AbstractTrain is a templated class for train implementations in a command station.
static constexpr unsigned VIRTF0_BLANK_REV
Function number of "Blank F0 Reverse".
uint32_t legacy_address() OVERRIDE
SpeedType get_commanded_speed() OVERRIDE
unsigned get_effective_f0()
void set_emergencystop() OVERRIDE
Sets the train to ESTOP state, generating an emergency stop packet.
SpeedType get_speed() OVERRIDE
P p
Payload – actual data we know about the train.
bool get_emergencystop() OVERRIDE
Gets the train's ESTOP state.
TrainAddressType legacy_address_type() OVERRIDE
void set_speed(SpeedType speed) OVERRIDE
Sets the train speed (asking for a high-priority outgoing update packet to be generated).
void update_f0_direction_changed()
Updates the f0 states after a direction change occurred.
uint16_t get_fn(uint32_t address) OVERRIDE
static constexpr unsigned VIRTF0_BLANK_FWD
Function number of "Blank F0 Forward".
static constexpr unsigned VIRTF0_DIRECTIONAL_ENABLE
Function number of "enable directional F0".
void set_fn(uint32_t address, uint16_t value) OVERRIDE
Sets a function to a given value.
TrainImpl class for a DCC locomotive.
DccTrain(DccLongAddress a)
Constructor.
DccTrain(DccShortAddress a)
Constructor.
void get_next_packet(unsigned code, Packet *packet) OVERRIDE
Generates next outgoing packet.
TrainImpl structure for Marklin-Motorola v2 protocol locomotives.
void get_next_packet(unsigned code, Packet *packet) OVERRIDE
Generates next outgoing packet.
TrainImpl structure for Marklin-Motorola v1 protocol locomotives.
void get_next_packet(unsigned code, Packet *packet) OVERRIDE
Generates next outgoing packet.
Abstract class for streams of DCC packets.
This class provides a mechanism for working with velocity in different forms.
void set_wire(float16_t value)
Set the value based on the wire version of velocity.
float16_t get_wire() const
Get a wire version of the velocity.
#define DECLARE_CONST(name)
Declares a constant value.
TrainAddressType
Which address type this legacy train node uses.
#define LOG(level, message...)
Conditionally write a message to the logging output.
static const int VERBOSE
Loglevel that is usually not printed, reporting debugging information.
#define OVERRIDE
Function attribute for virtual functions declaring that this funciton is overriding a funciton that s...
Structure defining the volatile state for a 128-speed-step DCC locomotive.
static unsigned get_speed_steps()
void add_dcc_speed_to_packet(dcc::Packet *p)
Adds the speed payload to a DCC packet.
void add_dcc_estop_to_packet(dcc::Packet *p)
Adds the speed payload to a DCC packet with value == EMERGENCY_STOP.
Structure defining the volatile state for a 28-speed-step DCC locomotive.
static unsigned get_speed_steps()
void add_dcc_speed_to_packet(dcc::Packet *p)
Adds the speed payload to a DCC packet.
void add_dcc_estop_to_packet(dcc::Packet *p)
Adds the speed payload to a DCC packet with value == EMERGENCY_STOP.
Strongly typed wrapper representing a long DCC address.
uint16_t value
Address value.
Common storage variables for the different DCC Payload types.
uint8_t speed_
Speed step we last set.
uint8_t f0OnForward_
1 if directional f0 is used and f0 is on for F.
bool get_fn_store(unsigned idx)
Get a given function bit in storage.
uint16_t lastSetSpeed_
fp16 value of the last set speed.
uint8_t f0BlankForward_
1 if F0 should be turned off when dir==forward.
uint8_t nextRefresh_
Which refresh packet should go out next.
uint16_t direction_
0: forward, 1: reverse
uint16_t address_
Track address. largest address allowed is 10239.
void set_fn_store(unsigned idx, bool value)
Set a given function bit in storage.
static unsigned get_fn_update_code(unsigned address)
unsigned fn_
functions f0-f28.
uint8_t fhi_[5]
f29-f68 state.
uint8_t isEstop_
1 if the last speed set was estop.
uint8_t f0BlankReverse_
1 if F0 should be turned off when dir==reverse.
static unsigned get_max_fn()
TrainAddressType get_address_type()
uint8_t f0OnReverse_
1 if directional f0 is used and f0 is on for R.
uint16_t isShortAddress_
1 if this is a short address train.
uint8_t f0SetDirectional_
1 if the F0 function should be set/get in a directional way.
uint8_t directionChanged_
Whether the direction change packet still needs to go out.
Strongly typed wrapper representing a short DCC address.
uint8_t value
Address value.
Strongly typed wrapper representing a marklin-motorola protocol address.
Structure defining the volatile state for a Marklin-Motorola v2 protocol locomotive (with 28 speed st...
unsigned nextRefresh_
internal refresh cycle state machine
unsigned speed_
Speed step we last set.
unsigned isEstop_
1 if the last speed set was estop.
unsigned f0BlankReverse_
1 if F0 should be turned off when dir==reverse.
unsigned direction_
0: forward, 1: reverse
unsigned f0OnReverse_
1 if directional f0 is used and f0 is on for R.
unsigned f0SetDirectional_
1 if the F0 function should be set/get in a directional way.
bool get_fn_store(unsigned idx)
Get a given function bit in storage.
void set_fn_store(unsigned idx, bool value)
Set a given function bit in storage.
unsigned f0OnForward_
1 if directional f0 is used and f0 is on for F.
unsigned get_fn_update_code(unsigned address)
unsigned directionChanged_
Whether the direction change packet still needs to go out.
static TrainAddressType get_address_type()
unsigned lastSetSpeed_
fp16 value of the last set speed.
unsigned address_
largest address allowed is 80, but we keep a few more bits around to allow for an extension to arbitr...
unsigned fn_
function f0-f4.
unsigned f0BlankForward_
1 if F0 should be turned off when dir==forward.
unsigned get_speed_steps()
Structure defining the volatile state for a Marklin-Motorola v1 protocol locomotive (with 14 speed st...
unsigned f0OnReverse_
1 if directional f0 is used and f0 is on for R.
unsigned f0BlankReverse_
1 if F0 should be turned off when dir==reverse.
unsigned address_
largest address allowed is 80, but we keep a few more bits around to allow for an extension to arbitr...
unsigned directionChanged_
Whether the direction change packet still needs to go out.
void set_fn_store(unsigned idx, bool value)
Set a given function bit in storage.
static TrainAddressType get_address_type()
unsigned f0OnForward_
1 if directional f0 is used and f0 is on for F.
unsigned isEstop_
1 if the last speed set was estop.
unsigned speed_
Speed step we last set.
unsigned f0SetDirectional_
1 if the F0 function should be set/get in a directional way.
unsigned direction_
0: forward, 1: reverse
unsigned get_fn_update_code(unsigned address)
unsigned f0BlankForward_
1 if F0 should be turned off when dir==forward.
unsigned get_speed_steps()
unsigned lastSetSpeed_
fp16 value of the last set speed.
bool get_fn_store(unsigned idx)
Get a given function bit in storage.
Represents a command to be sent to the track driver.
void add_dcc_speed28(bool is_fwd, unsigned speed)
Adds a speed-and-direction command (dcc baseline command) to the packet.
static const unsigned EMERGENCY_STOP
Send this speed step to emergency-stop the locomotive.
void add_dcc_speed128(bool is_fwd, unsigned speed)
Adds a speed-and-direction command (dcc extended command) for 128 speed steps to the packet.