-/* $Id$
-
-This file is part of the MSP Märklin suite
-Copyright © 2010 Mikkosoft Productions, Mikko Rasa
-Distributed under the GPL
-*/
-
-#ifndef LIBMARKLIN_INTELLIBOX_H_
-#define LIBMARKLIN_INTELLIBOX_H_
-
-#include <map>
-#include <msp/time/timestamp.h>
-#include "driver.h"
-
-namespace Marklin {
-
-/**
-Driver for Uhlenbrock Intellibox. Uses the P50X binary protocol over RS232.
-
-Motorola decoders with 27 speed steps are supported by manually generating the
-commands necessary to reach the "half-steps". However, sending a rapid stream
-of speed changes to the same locomotive seems to cause excessive lag, so we
-cheat a bit; instead of sending the half-step command immediately, we send it
-with a 500ms delay, but only if no new set_loco_speed calls have occurred. As
-a downside from this accelerations and decelerations are still jerky.
-*/
-class Intellibox: public Driver
-{
-private:
- enum Command
- {
- CMD_LOK=0x80,
- CMD_LOK_STATUS=0x84,
- CMD_LOK_CONFIG=0x85,
- CMD_FUNC=0x88,
- CMD_FUNC_STATUS=0x8C,
- CMD_TURNOUT=0x90,
- CMD_TURNOUT_FREE=0x93,
- CMD_TURNOUT_STATUS=0x94,
- CMD_TURNOUT_GROUP_STATUS=0x95,
- CMD_SENSOR_STATUS=0x98,
- CMD_SENSOR_REPORT=0x99,
- CMD_SENSOR_PARAM_SET=0x9D,
- CMD_STATUS=0xA2,
- CMD_POWER_OFF=0xA6,
- CMD_POWER_ON=0xA7,
- CMD_NOP=0xC4,
- CMD_EVENT=0xC8,
- CMD_EVENT_LOK=0xC9,
- CMD_EVENT_TURNOUT=0xCA,
- CMD_EVENT_SENSOR=0xCB
- };
-
- enum Error
- {
- ERR_NO_ERROR=0,
- ERR_SYS_ERROR,
- ERR_BAD_PARAM,
- ERR_POWER_OFF=0x6,
- ERR_NO_LOK_SPACE=0x8, // No space in lok command buffer
- ERR_NO_TURNOUT_SPACE, // No space in turnout command buffer
- ERR_NO_DATA, // "no Lok status available (Lok is not in a slot)"
- ERR_NO_SLOT, // "there is no slot available"
- ERR_BAD_LOK_ADDR,
- ERR_LOK_BUSY,
- ERR_BAD_TURNOUT_ADDR,
- ERR_BAD_SO_VALUE,
- ERR_NO_I2C_SPACE,
- ERR_LOW_TURNOUT_SPACE=0x40,
- ERR_LOK_HALTED,
- ERR_LOK_POWER_OFF,
- };
-
- enum Protocol
- {
- MM,
- MM_27
- };
-
- struct Locomotive
- {
- Protocol protocol;
- unsigned speed;
- bool reverse;
- unsigned funcs;
- int pending_half_step;
- Msp::Time::TimeStamp half_step_delay;
-
- Locomotive();
- };
-
- struct Turnout
- {
- bool state;
- bool active;
- bool pending;
- Msp::Time::TimeStamp off_timeout;
-
- Turnout();
- };
-
- struct Sensor
- {
- bool state;
- Msp::Time::TimeStamp off_timeout;
-
- Sensor();
- };
-
- struct CommandSlot
- {
- Command cmd;
- unsigned addr;
- unsigned char data[8];
- unsigned length;
- };
-
- int serial_fd;
- bool power;
- bool halted;
- std::map<unsigned, Locomotive> locos;
- std::map<unsigned, Turnout> turnouts;
- std::map<unsigned, Sensor> sensors;
- bool update_sensors;
- std::list<CommandSlot> queue;
- bool command_sent;
- Msp::Time::TimeStamp next_event_query;
-
-public:
- Intellibox(const std::string &);
-
- virtual void set_power(bool);
- virtual bool get_power() const { return power; }
- virtual void halt(bool);
- virtual bool is_halted() const { return halted; }
-
- virtual const char *enumerate_protocols(unsigned) const;
- virtual unsigned get_protocol_speed_steps(const std::string &) const;
- virtual void add_loco(unsigned, const std::string &);
- virtual void set_loco_speed(unsigned, unsigned);
- virtual void set_loco_reverse(unsigned, bool);
- virtual void set_loco_function(unsigned, unsigned, bool);
-
- virtual void add_turnout(unsigned);
- virtual void set_turnout(unsigned, bool);
- virtual bool get_turnout(unsigned) const;
-
- virtual void add_sensor(unsigned);
- virtual void set_sensor(unsigned, bool) { }
- virtual bool get_sensor(unsigned) const;
-
- virtual void tick();
- virtual void flush();
-
-private:
- Protocol map_protocol(const std::string &) const;
- void command(Command);
- void command(Command, const unsigned char *, unsigned);
- void command(Command, unsigned, const unsigned char *, unsigned);
- void loco_command(unsigned, unsigned, bool, unsigned);
- void turnout_command(unsigned, bool, bool);
- void process_reply(const Msp::Time::TimeStamp &);
- unsigned read_all(unsigned char *, unsigned);
- unsigned read_status(Error *);
- void error(Command, Error);
-};
-
-} // namespace Marklin
-
-#endif