1 #ifndef LIBR2C2_INTELLIBOX_H_
2 #define LIBR2C2_INTELLIBOX_H_
5 #include <msp/io/serial.h>
6 #include <msp/time/timestamp.h>
12 Driver for Uhlenbrock Intellibox. Uses the P50X binary protocol over RS232.
14 Motorola decoders with 27 speed steps are supported by manually generating the
15 commands necessary to reach the "half-steps". However, sending a rapid stream
16 of speed changes to the same locomotive seems to cause excessive lag, so we
17 cheat a bit; instead of sending the half-step command immediately, we send it
18 with a 500ms delay, but only if no new set_loco_speed calls have occurred. As
19 a downside from this accelerations and decelerations are still jerky.
21 class Intellibox: public Driver
32 CMD_TURNOUT_FREE=0x93,
33 CMD_TURNOUT_STATUS=0x94,
34 CMD_TURNOUT_GROUP_STATUS=0x95,
35 CMD_SENSOR_STATUS=0x98,
36 CMD_SENSOR_REPORT=0x99,
37 CMD_SENSOR_PARAM_SET=0x9D,
44 CMD_EVENT_TURNOUT=0xCA,
54 ERR_NO_LOK_SPACE=0x8, // No space in lok command buffer
55 ERR_NO_TURNOUT_SPACE, // No space in turnout command buffer
56 ERR_NO_DATA, // "no Lok status available (Lok is not in a slot)"
57 ERR_NO_SLOT, // "there is no slot available"
63 ERR_LOW_TURNOUT_SPACE=0x40,
82 int pending_half_step;
83 Msp::Time::TimeStamp half_step_delay;
88 // These are used for signals as well, but Intellibox calls them turnouts.
96 Msp::Time::TimeStamp off_timeout;
105 Msp::Time::TimeStamp off_timeout;
114 unsigned char data[8];
118 Msp::IO::Serial serial;
121 std::map<unsigned, Locomotive> locos;
122 std::map<unsigned, Turnout> turnouts;
123 std::map<unsigned, Sensor> sensors;
125 std::list<CommandSlot> queue;
127 Msp::Time::TimeStamp next_event_query;
130 Intellibox(const Options &);
132 virtual void set_power(bool);
133 virtual bool get_power() const { return power; }
134 virtual void halt(bool);
135 virtual bool is_halted() const { return halted; }
137 virtual const char *enumerate_protocols(unsigned) const;
138 virtual unsigned get_protocol_speed_steps(const std::string &) const;
139 virtual DetectedLocomotive *enumerate_detected_locos(unsigned) const { return 0; }
140 virtual unsigned add_loco(unsigned, const std::string &, const VehicleType &);
141 virtual void remove_loco(unsigned);
142 virtual void set_loco_speed(unsigned, unsigned);
143 virtual void set_loco_reverse(unsigned, bool);
144 virtual void set_loco_function(unsigned, unsigned, bool);
146 virtual unsigned add_turnout(unsigned, const TrackType &);
147 virtual void remove_turnout(unsigned);
149 unsigned add_turnout(unsigned, unsigned, bool);
150 void turnout_state_changed(unsigned, const Turnout &) const;
152 virtual void set_turnout(unsigned, unsigned);
153 virtual unsigned get_turnout(unsigned) const;
155 virtual unsigned add_signal(unsigned, const SignalType &);
156 virtual void remove_signal(unsigned);
157 virtual void set_signal(unsigned, unsigned);
158 virtual unsigned get_signal(unsigned) const;
161 virtual unsigned add_sensor(unsigned);
162 virtual void remove_sensor(unsigned);
163 virtual void set_sensor(unsigned, bool) { }
164 virtual bool get_sensor(unsigned) const;
166 virtual const TelemetryInfo *enumerate_telemetry(unsigned) const { return 0; }
167 virtual float get_telemetry_value(const std::string &) const;
170 virtual void flush();
173 Protocol map_protocol(const std::string &) const;
174 void command(Command);
175 void command(Command, const unsigned char *, unsigned);
176 void command(Command, unsigned, const unsigned char *, unsigned);
177 void loco_command(unsigned, unsigned, bool, unsigned, bool);
178 void turnout_command(unsigned, bool, bool);
179 void process_reply(const Msp::Time::TimeStamp &);
180 unsigned read_all(unsigned char *, unsigned);
181 unsigned read_status(Error *);
182 void error(Command, Error);