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;
95 Msp::Time::TimeStamp off_timeout;
103 Msp::Time::TimeStamp off_timeout;
112 unsigned char data[8];
116 Msp::IO::Serial serial;
119 std::map<unsigned, Locomotive> locos;
120 std::map<unsigned, Turnout> turnouts;
121 std::map<unsigned, Sensor> sensors;
123 std::list<CommandSlot> queue;
125 Msp::Time::TimeStamp next_event_query;
128 Intellibox(const std::string &);
130 virtual void set_power(bool);
131 virtual bool get_power() const { return power; }
132 virtual void halt(bool);
133 virtual bool is_halted() const { return halted; }
135 virtual const char *enumerate_protocols(unsigned) const;
136 virtual unsigned get_protocol_speed_steps(const std::string &) const;
137 virtual void add_loco(unsigned, const std::string &, const VehicleType &);
138 virtual void set_loco_speed(unsigned, unsigned);
139 virtual void set_loco_reverse(unsigned, bool);
140 virtual void set_loco_function(unsigned, unsigned, bool);
142 virtual void add_turnout(unsigned, const TrackType &);
143 virtual void set_turnout(unsigned, unsigned);
144 virtual unsigned get_turnout(unsigned) const;
146 // TODO implement these
147 virtual void add_signal(unsigned, const SignalType &) { }
148 virtual void set_signal(unsigned, unsigned) { }
149 virtual unsigned get_signal(unsigned) const { return 0; }
151 virtual void add_sensor(unsigned);
152 virtual void set_sensor(unsigned, bool) { }
153 virtual bool get_sensor(unsigned) const;
156 virtual void flush();
159 Protocol map_protocol(const std::string &) const;
160 void command(Command);
161 void command(Command, const unsigned char *, unsigned);
162 void command(Command, unsigned, const unsigned char *, unsigned);
163 void loco_command(unsigned, unsigned, bool, unsigned, bool);
164 void turnout_command(unsigned, bool, bool);
165 void process_reply(const Msp::Time::TimeStamp &);
166 unsigned read_all(unsigned char *, unsigned);
167 unsigned read_status(Error *);
168 void error(Command, Error);