X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibr2c2%2Farducontrol.h;h=fffaf8cc36854d691860e8064548fcd589579aac;hb=b85fa11e45805cd71383577642030d8d01f43447;hp=4e9ef63b248c631821055aecf2ad0bc53ce5fbeb;hpb=daecd71f20c275fb6df128a3aaa4cfdda24b6886;p=r2c2.git diff --git a/source/libr2c2/arducontrol.h b/source/libr2c2/arducontrol.h index 4e9ef63..fffaf8c 100644 --- a/source/libr2c2/arducontrol.h +++ b/source/libr2c2/arducontrol.h @@ -1,8 +1,11 @@ #ifndef LIBR2C2_ARDUCONTROL_H_ #define LIBR2C2_ARDUCONTROL_H_ +#include #include #include +#include +#include #include #include #include @@ -12,6 +15,17 @@ namespace R2C2 { class ArduControl: public Driver { +public: + class Loader: public Msp::DataFile::ObjectLoader + { + public: + Loader(ArduControl &); + + private: + void mfx_announce_serial(unsigned); + void mfx_locomotive(unsigned); + }; + private: enum Command { @@ -26,7 +40,17 @@ private: MOTOROLA_SPEED_DIRECTION = 0x13, MOTOROLA_SPEED_FUNCTION = 0x14, MOTOROLA_SOLENOID = 0x15, + MFX_SET_STATION_ID = 0x21, + MFX_ANNOUNCE = 0x22, + MFX_SEARCH = 0x23, + MFX_ASSIGN_ADDRESS = 0x24, + MFX_PING = 0x25, + MFX_READ = 0x26, + MFX_SPEED = 0x28, + MFX_SPEED_FUNCS8 = 0x29, + MFX_SPEED_FUNCS16 = 0x2A, S88_READ = 0x30, + SET_BAUD_RATE = 0x70, COMMAND_OK = 0x80, RECEIVE_OVERRUN = 0x81, FRAMING_ERROR = 0x82, @@ -34,10 +58,14 @@ private: LENGTH_ERROR = 0x84, INVALID_VALUE = 0x85, OVERCURRENT = 0xA0, + BAUD_CHANGE_FAILED = 0xA1, TRACK_CURRENT = 0xC0, INPUT_VOLTAGE = 0xC1, POWER_STATE = 0xC2, - S88_DATA = 0xD0 + S88_DATA = 0xD0, + MFX_SEARCH_FEEDBACK = 0xD1, + MFX_PING_FEEDBACK = 0xD2, + MFX_READ_FEEDBACK = 0xD3 }; struct Tag @@ -63,12 +91,14 @@ private: enum GeneralCommand { - POWER + POWER, + NEW_LOCO }; enum Protocol { - MM + MM, + MFX }; struct ProtocolInfo @@ -90,6 +120,7 @@ private: bool set(T v) { if(v==pending) return false; pending = v; ++serial; return true; } bool commit(unsigned short s) { if(s!=serial) return false; current = pending; return true; } + void rollback() { pending = current; ++serial; } operator T() const { return current; } }; @@ -117,6 +148,17 @@ private: unsigned create_speed_func_command(unsigned, char *) const; }; + struct MfxInfo: public DetectedLocomotive + { + class Loader: public Msp::DataFile::ObjectLoader + { + public: + Loader(MfxInfo &); + }; + + unsigned id; + }; + struct Accessory { enum Kind @@ -134,11 +176,13 @@ private: Kind kind; unsigned address; unsigned bits; + unsigned valid_states; ControlledVariable state; + unsigned uncertain; unsigned target; Msp::Time::TimeDelta active_time; - Accessory(Kind, unsigned, unsigned); + Accessory(Kind, unsigned, unsigned, unsigned); unsigned create_state_command(unsigned, bool, char *) const; }; @@ -156,70 +200,246 @@ private: Sensor(unsigned); }; + struct PendingCommand + { + Tag tag; + char command[15]; + unsigned char length; + unsigned repeat_count; + + PendingCommand(); + PendingCommand(GeneralCommand); + PendingCommand(Locomotive &, Locomotive::Command, unsigned = 0); + PendingCommand(Accessory &, Accessory::Command, unsigned = 0); + }; + + template + class Queue + { + private: + std::deque items; + Msp::Mutex mutex; + + public: + void push(const T &); + bool pop(T &); + unsigned size() const; + bool empty() const; + }; + + class Task + { + protected: + std::string name; + unsigned priority; + Msp::Time::TimeStamp sleep_timeout; + + Task(const std::string &, unsigned = 0); + public: + virtual ~Task() { } + + const std::string &get_name() const { return name; } + + virtual bool get_work(PendingCommand &) = 0; + virtual void process_reply(const char *, unsigned) { } + + unsigned get_priority() const { return priority; } + const Msp::Time::TimeStamp &get_sleep_timeout() const { return sleep_timeout; } + protected: + void sleep(const Msp::Time::TimeDelta &); + }; + + class CommandQueueTask: public Task + { + private: + Queue queue; + + public: + CommandQueueTask(); + + virtual bool get_work(PendingCommand &); + + void push(const PendingCommand &); + unsigned size() const { return queue.size(); } + bool empty() const { return queue.empty(); } + }; + + class RefreshTask: public Task + { + private: + typedef std::list LocomotivePtrList; + + LocomotivePtrList cycle; + LocomotivePtrList::iterator next; + unsigned round; + Locomotive *loco; + unsigned phase; + Msp::Mutex mutex; + + public: + RefreshTask(); + + virtual bool get_work(PendingCommand &); + + void add_loco(Locomotive &); + void remove_loco(Locomotive &); + private: + Locomotive *get_next_loco(); + void advance(); + }; + + class S88Task: public Task + { + private: + ArduControl &control; + unsigned n_octets; + unsigned octets_remaining; + Msp::Time::TimeStamp last_poll; + Msp::Time::TimeDelta latency; + + public: + S88Task(ArduControl &); + + virtual bool get_work(PendingCommand &); + virtual void process_reply(const char *, unsigned); + + void set_n_octets(unsigned); + void grow_n_octets(unsigned); + + const Msp::Time::TimeDelta &get_latency() const { return latency; } + }; + + class MfxAnnounceTask: public Task + { + private: + unsigned serial; + + public: + MfxAnnounceTask(); + + virtual bool get_work(PendingCommand &); + + void set_serial(unsigned); + unsigned get_serial() const { return serial; } + }; + + class MfxSearchTask: public Task + { + private: + ArduControl &control; + unsigned next_address; + unsigned size; + unsigned bits; + unsigned misses; + Queue queue; + + MfxInfo *pending_info; + unsigned read_array; + unsigned read_offset; + unsigned read_length; + char read_data[0x40]; + unsigned block_size; + + public: + MfxSearchTask(ArduControl &); + + virtual bool get_work(PendingCommand &); + virtual void process_reply(const char *, unsigned); + + void set_next_address(unsigned); + bool pop_info(MfxInfo &); + }; + + class MonitorTask: public Task + { + private: + float voltage; + float current; + float base_level; + float peak_level; + unsigned next_type; + + public: + MonitorTask(); + + virtual bool get_work(PendingCommand &); + virtual void process_reply(const char *, unsigned); + + float get_voltage() const { return voltage; } + float get_current() const { return current; } + void reset_peak(); + float get_peak() const { return peak_level-base_level; } + }; + class ControlThread: public Msp::Thread { private: ArduControl &control; bool done; + std::vector tasks; + unsigned cmd_rate; + unsigned cmd_count; + Msp::Time::TimeStamp cmd_rate_start; public: ControlThread(ArduControl &); + unsigned get_command_rate() const { return cmd_rate; } + void exit(); private: virtual void main(); - }; - - struct QueuedCommand - { - Tag tag; - char command[15]; - unsigned char length; - - QueuedCommand(); - QueuedCommand(GeneralCommand); - QueuedCommand(Locomotive &, Locomotive::Command, unsigned = 0); - QueuedCommand(Accessory &, Accessory::Command, unsigned = 0); + void init_baud_rate(); + bool get_work(PendingCommand &); + unsigned do_command(const PendingCommand &, const Msp::Time::TimeDelta &); + unsigned process_reply(const char *, unsigned); + void set_power(bool); }; typedef std::map LocomotiveMap; - typedef std::list LocomotivePtrList; + typedef std::vector MfxInfoArray; typedef std::map AccessoryMap; typedef std::list AccessoryPtrList; typedef std::map SensorMap; Msp::IO::Serial serial; - bool debug; + unsigned debug; + Msp::FS::Path state_file; ControlledVariable power; + bool halted; LocomotiveMap locomotives; - LocomotivePtrList refresh_cycle; - LocomotivePtrList::iterator next_refresh; - unsigned refresh_counter; + MfxInfoArray mfx_info; AccessoryMap accessories; AccessoryPtrList accessory_queue; Accessory *active_accessory; + unsigned char active_index; Msp::Time::TimeStamp off_timeout; - std::list command_queue; - std::list completed_commands; SensorMap sensors; - unsigned n_s88_octets; - Msp::Mutex mutex; + Msp::Time::TimeDelta command_timeout; + CommandQueueTask command_queue; + Queue completed_commands; + RefreshTask refresh; + S88Task s88; + MfxAnnounceTask mfx_announce; + MfxSearchTask mfx_search; + MonitorTask monitor; ControlThread thread; static ProtocolInfo protocol_info[2]; + static TelemetryInfo telemetry_info[6]; public: - ArduControl(const std::string &); + ArduControl(const Options &); ~ArduControl(); virtual void set_power(bool); virtual bool get_power() const { return power; } virtual void halt(bool); - virtual bool is_halted() const { return false; } + virtual bool is_halted() const { return halted; } virtual const char *enumerate_protocols(unsigned) const; private: @@ -227,18 +447,17 @@ private: public: virtual unsigned get_protocol_speed_steps(const std::string &) const; + virtual const DetectedLocomotive *enumerate_detected_locos(unsigned) const; virtual unsigned add_loco(unsigned, const std::string &, const VehicleType &); +private: + MfxInfoArray::iterator add_mfx_info(const MfxInfo &); + MfxInfo *find_mfx_info(unsigned); +public: virtual void remove_loco(unsigned); virtual void set_loco_speed(unsigned, unsigned); virtual void set_loco_reverse(unsigned, bool); virtual void set_loco_function(unsigned, unsigned, bool); -private: - void add_loco_to_refresh(Locomotive &); - void remove_loco_from_refresh(Locomotive &); - Locomotive *get_loco_to_refresh(); - void advance_next_refresh(); -public: virtual unsigned add_turnout(unsigned, const TrackType &); virtual void remove_turnout(unsigned); virtual void set_turnout(unsigned, unsigned); @@ -250,10 +469,11 @@ public: virtual unsigned get_signal(unsigned) const; private: - unsigned add_accessory(Accessory::Kind, unsigned, unsigned); + unsigned add_accessory(Accessory::Kind, unsigned, unsigned, unsigned); void remove_accessory(Accessory::Kind, unsigned); void set_accessory(Accessory::Kind, unsigned, unsigned); unsigned get_accessory(Accessory::Kind, unsigned) const; + void activate_accessory_by_mask(Accessory &, unsigned); public: virtual unsigned add_sensor(unsigned); @@ -261,14 +481,13 @@ public: virtual void set_sensor(unsigned, bool) { } virtual bool get_sensor(unsigned) const; + virtual const TelemetryInfo *enumerate_telemetry(unsigned) const; + virtual float get_telemetry_value(const std::string &) const; + virtual void tick(); virtual void flush(); - private: - void push_command(const QueuedCommand &); - bool pop_command(QueuedCommand &); - void push_completed_tag(const Tag &); - Tag pop_completed_tag(); + void save_state() const; }; } // namespace R2C2