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 std::string &);
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 void add_loco(unsigned, const std::string &, const VehicleType &);
140 virtual void set_loco_speed(unsigned, unsigned);
141 virtual void set_loco_reverse(unsigned, bool);
142 virtual void set_loco_function(unsigned, unsigned, bool);
144 virtual void add_turnout(unsigned, const TrackType &);
146 void add_turnout(unsigned, unsigned, bool);
147 void turnout_state_changed(unsigned, const Turnout &) const;
149 virtual void set_turnout(unsigned, unsigned);
150 virtual unsigned get_turnout(unsigned) const;
152 virtual void add_signal(unsigned, const SignalType &);
153 virtual void set_signal(unsigned, unsigned);
154 virtual unsigned get_signal(unsigned) const;
157 virtual void add_sensor(unsigned);
158 virtual void set_sensor(unsigned, bool) { }
159 virtual bool get_sensor(unsigned) const;
162 virtual void flush();
165 Protocol map_protocol(const std::string &) const;
166 void command(Command);
167 void command(Command, const unsigned char *, unsigned);
168 void command(Command, unsigned, const unsigned char *, unsigned);
169 void loco_command(unsigned, unsigned, bool, unsigned, bool);
170 void turnout_command(unsigned, bool, bool);
171 void process_reply(const Msp::Time::TimeStamp &);
172 unsigned read_all(unsigned char *, unsigned);
173 unsigned read_status(Error *);
174 void error(Command, Error);