From: Mikko Rasa Date: Mon, 22 Nov 2010 20:42:23 +0000 (+0000) Subject: Move double-address logic to drivers X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=247742fbc1c27bfc9fdef4630afcdc2408cdd550;p=r2c2.git Move double-address logic to drivers --- diff --git a/source/libr2c2/driver.h b/source/libr2c2/driver.h index d9d1127..e8d27f0 100644 --- a/source/libr2c2/driver.h +++ b/source/libr2c2/driver.h @@ -13,6 +13,9 @@ Distributed under the GPL namespace R2C2 { +class TrackType; +class VehicleType; + class Driver { public: @@ -20,7 +23,7 @@ public: sigc::signal signal_halt; sigc::signal signal_loco_speed; sigc::signal signal_loco_function; - sigc::signal signal_turnout; + sigc::signal signal_turnout; sigc::signal signal_sensor; protected: @@ -35,14 +38,14 @@ public: virtual const char *enumerate_protocols(unsigned) const = 0; virtual unsigned get_protocol_speed_steps(const std::string &) const = 0; - virtual void add_loco(unsigned, const std::string &) = 0; + virtual void add_loco(unsigned, const std::string &, const VehicleType &) = 0; virtual void set_loco_speed(unsigned, unsigned) = 0; virtual void set_loco_reverse(unsigned, bool) = 0; virtual void set_loco_function(unsigned, unsigned, bool) = 0; - virtual void add_turnout(unsigned) = 0; - virtual void set_turnout(unsigned, bool) = 0; - virtual bool get_turnout(unsigned) const = 0; + virtual void add_turnout(unsigned, const TrackType &) = 0; + virtual void set_turnout(unsigned, unsigned) = 0; + virtual unsigned get_turnout(unsigned) const = 0; virtual void add_sensor(unsigned) = 0; virtual void set_sensor(unsigned, bool) = 0; diff --git a/source/libr2c2/dummy.cpp b/source/libr2c2/dummy.cpp index 814dce4..9c78234 100644 --- a/source/libr2c2/dummy.cpp +++ b/source/libr2c2/dummy.cpp @@ -33,12 +33,12 @@ unsigned Dummy::get_protocol_speed_steps(const string &) const return 0; } -void Dummy::add_turnout(unsigned addr) +void Dummy::add_turnout(unsigned addr, const TrackType &) { turnouts[addr]; } -void Dummy::set_turnout(unsigned addr, bool state) +void Dummy::set_turnout(unsigned addr, unsigned state) { if(turnouts[addr]!=state) { @@ -47,9 +47,9 @@ void Dummy::set_turnout(unsigned addr, bool state) } } -bool Dummy::get_turnout(unsigned addr) const +unsigned Dummy::get_turnout(unsigned addr) const { - map::const_iterator i = turnouts.find(addr); + map::const_iterator i = turnouts.find(addr); if(i!=turnouts.end()) return i->second; return false; diff --git a/source/libr2c2/dummy.h b/source/libr2c2/dummy.h index 5357bbd..d388ca6 100644 --- a/source/libr2c2/dummy.h +++ b/source/libr2c2/dummy.h @@ -23,7 +23,7 @@ private: }; bool power; - std::map turnouts; + std::map turnouts; std::map locos; std::map sensors; @@ -37,14 +37,14 @@ public: 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 add_loco(unsigned, const std::string &, const VehicleType &) { } 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_turnout(unsigned, const TrackType &); + virtual void set_turnout(unsigned, unsigned); + virtual unsigned get_turnout(unsigned) const; virtual void add_sensor(unsigned) { } virtual void set_sensor(unsigned, bool); diff --git a/source/libr2c2/intellibox.cpp b/source/libr2c2/intellibox.cpp index 9ac448e..64e7855 100644 --- a/source/libr2c2/intellibox.cpp +++ b/source/libr2c2/intellibox.cpp @@ -12,6 +12,8 @@ Distributed under the GPL #include #include #include "intellibox.h" +#include "tracktype.h" +#include "vehicletype.h" using namespace std; using namespace Msp; @@ -96,6 +98,7 @@ void Intellibox::halt(bool h) const char *Intellibox::enumerate_protocols(unsigned i) const { + ++i; if(i==MM) return "MM"; else if(i==MM_27) @@ -113,13 +116,19 @@ unsigned Intellibox::get_protocol_speed_steps(const string &proto_name) const return 0; } -void Intellibox::add_loco(unsigned addr, const string &proto_name) +void Intellibox::add_loco(unsigned addr, const string &proto_name, const VehicleType &type) { Protocol proto = map_protocol(proto_name); if(!locos.count(addr)) { - locos[addr].protocol = proto; + Locomotive &loco = locos[addr]; + loco.protocol = proto; + if(type.get_max_function()>4) + { + loco.ext_func = true; + locos[addr+1].protocol = NONE; + } unsigned char data[2]; data[0] = addr&0xFF; @@ -131,6 +140,9 @@ void Intellibox::add_loco(unsigned addr, const string &proto_name) void Intellibox::set_loco_speed(unsigned addr, unsigned speed) { Locomotive &loco = locos[addr]; + if(loco.protocol==NONE) + return; + if(speed==loco.speed) { if(loco.pending_half_step) @@ -163,14 +175,14 @@ void Intellibox::set_loco_speed(unsigned addr, unsigned speed) loco.pending_half_step = 0; loco.half_step_delay = Time::TimeStamp(); - loco_command(addr, (speed+1)/2, loco.reverse, loco.funcs|0x100); + loco_command(addr, (speed+1)/2, loco.reverse, loco.funcs, false); } - else + else if(loco.protocol==MM) { if(speed>14) speed = 14; - loco_command(addr, speed, loco.reverse, loco.funcs|0x100); + loco_command(addr, speed, loco.reverse, loco.funcs, false); } loco.speed = speed; } @@ -178,56 +190,82 @@ void Intellibox::set_loco_speed(unsigned addr, unsigned speed) void Intellibox::set_loco_reverse(unsigned addr, bool rev) { Locomotive &loco = locos[addr]; - if(rev==loco.reverse) + if(loco.protocol==NONE || rev==loco.reverse) return; + loco.speed = 0; loco.reverse = rev; - loco_command(addr, loco.speed, rev, loco.funcs|0x100); + loco_command(addr, 0, rev, loco.funcs, false); } void Intellibox::set_loco_function(unsigned addr, unsigned func, bool state) { Locomotive &loco = locos[addr]; + if(loco.protocol==NONE) + return; + if(state) loco.funcs |= 1<>4)&0x1E, true); signal_loco_function.emit(addr, func, state); } -void Intellibox::add_turnout(unsigned addr) +void Intellibox::add_turnout(unsigned addr, const TrackType &type) { if(!turnouts.count(addr)) { - turnouts[addr]; + Turnout &turnout = turnouts[addr]; + turnout.bits = type.get_state_bits(); unsigned char data[2]; data[0] = addr&0xFF; data[1] = (addr>>8)&0xFF; command(CMD_TURNOUT_STATUS, addr, data, 2); + for(unsigned i=1; i::const_iterator i = turnouts.find(addr); if(i!=turnouts.end()) return i->second.state; - return false; + return 0; } void Intellibox::add_sensor(unsigned addr) @@ -263,7 +301,7 @@ void Intellibox::tick() i->second.speed += i->second.pending_half_step; i->second.pending_half_step = 0; i->second.half_step_delay = Time::TimeStamp(); - loco_command(i->first, (i->second.speed+1)/2, i->second.reverse, i->second.funcs|0x100); + loco_command(i->first, (i->second.speed+1)/2, i->second.reverse, i->second.funcs, false); } for(map::iterator i=turnouts.begin(); i!=turnouts.end(); ++i) @@ -365,7 +403,7 @@ void Intellibox::command(Command cmd, unsigned addr, const unsigned char *data, queue.push_back(slot); } -void Intellibox::loco_command(unsigned addr, unsigned speed, bool rev, unsigned funcs) +void Intellibox::loco_command(unsigned addr, unsigned speed, bool rev, unsigned funcs, bool setf) { unsigned char data[4]; data[0] = addr&0xFF; @@ -380,7 +418,7 @@ void Intellibox::loco_command(unsigned addr, unsigned speed, bool rev, unsigned data[3] = (rev ? 0 : 0x20) | ((funcs&1) ? 0x10 : 0); - if(!(funcs&0x100)) + if(setf) data[3] |= 0x80 | ((funcs>>1)&0xF); command(CMD_LOK, addr, data, 4); @@ -498,9 +536,12 @@ void Intellibox::process_reply(const Time::TimeStamp &t) { unsigned addr = queue.front().addr; Locomotive &loco = locos[addr]; - signal_loco_speed.emit(addr, loco.speed+loco.pending_half_step, loco.reverse); - if(loco.pending_half_step) - loco.half_step_delay = Time::now()+500*Time::msec; + if(loco.protocol) + { + signal_loco_speed.emit(addr, loco.speed+loco.pending_half_step, loco.reverse); + if(loco.pending_half_step) + loco.half_step_delay = Time::now()+500*Time::msec; + } } else error(cmd, err); @@ -511,14 +552,21 @@ void Intellibox::process_reply(const Time::TimeStamp &t) read_status(&err); unsigned addr = queue.front().addr; + unsigned mask = 1; + while(!turnouts[addr].bits) + { + --addr; + mask <<= 1; + } Turnout &turnout = turnouts[addr]; if(err==ERR_NO_ERROR) { - turnout.state = turnout.pending; + turnout.state = (turnout.state&~mask) | (turnout.pending&mask); if(turnout.active) { - signal_turnout.emit(addr, turnout.state); + if(turnout.state==turnout.pending) + signal_turnout.emit(addr, turnout.state); turnout.off_timeout = t+500*Time::msec; } } @@ -526,7 +574,7 @@ void Intellibox::process_reply(const Time::TimeStamp &t) queue.push_back(queue.front()); else { - turnout.pending = turnout.state; + turnout.pending = (turnout.pending&~mask) | (turnout.state&mask); error(cmd, err); } } @@ -541,13 +589,19 @@ void Intellibox::process_reply(const Time::TimeStamp &t) read_all(&data, 1); unsigned addr = queue.front().addr; - bool state = data&0x04; - + unsigned mask = 1; + while(!turnouts[addr].bits) + { + --addr; + mask <<= 1; + } Turnout &turnout = turnouts[addr]; - if(state!=turnout.state) + + bool state = data&0x04; + if(state!=((turnout.state&mask)!=0)) { - turnout.state = state; - turnout.pending = state; + turnout.state = (turnout.state&~mask) | (state ? mask : 0); + turnout.pending = turnout.state; signal_turnout.emit(addr, turnout.state); } } @@ -686,6 +740,7 @@ void Intellibox::error(Command cmd, Error err) Intellibox::Locomotive::Locomotive(): + ext_func(false), speed(0), reverse(false), funcs(0) @@ -693,7 +748,8 @@ Intellibox::Locomotive::Locomotive(): Intellibox::Turnout::Turnout(): - state(false), + bits(1), + state(0), active(false), pending(false) { } diff --git a/source/libr2c2/intellibox.h b/source/libr2c2/intellibox.h index 8655bfc..a4eed30 100644 --- a/source/libr2c2/intellibox.h +++ b/source/libr2c2/intellibox.h @@ -73,6 +73,7 @@ private: enum Protocol { + NONE, MM, MM_27 }; @@ -80,6 +81,7 @@ private: struct Locomotive { Protocol protocol; + bool ext_func; unsigned speed; bool reverse; unsigned funcs; @@ -91,9 +93,10 @@ private: struct Turnout { - bool state; + unsigned bits; + unsigned state; bool active; - bool pending; + unsigned pending; Msp::Time::TimeStamp off_timeout; Turnout(); @@ -136,14 +139,14 @@ public: 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 add_loco(unsigned, const std::string &, const VehicleType &); 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_turnout(unsigned, const TrackType &); + virtual void set_turnout(unsigned, unsigned); + virtual unsigned get_turnout(unsigned) const; virtual void add_sensor(unsigned); virtual void set_sensor(unsigned, bool) { } @@ -157,7 +160,7 @@ private: 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 loco_command(unsigned, unsigned, bool, unsigned, bool); void turnout_command(unsigned, bool, bool); void process_reply(const Msp::Time::TimeStamp &); unsigned read_all(unsigned char *, unsigned); diff --git a/source/libr2c2/layout.cpp b/source/libr2c2/layout.cpp index 3e49f19..a55819b 100644 --- a/source/libr2c2/layout.cpp +++ b/source/libr2c2/layout.cpp @@ -84,7 +84,7 @@ void Layout::remove_track(Track &t) } } -unsigned Layout::allocate_turnout_id(bool dbl) +unsigned Layout::allocate_turnout_id() { set used_ids; for(set::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) @@ -92,9 +92,9 @@ unsigned Layout::allocate_turnout_id(bool dbl) used_ids.insert((*i)->get_turnout_id()); unsigned result = next_turnout_id; - while(used_ids.count(result) || (dbl && used_ids.count(result+1))) + while(used_ids.count(result)) ++result; - next_turnout_id = result+1+dbl; + next_turnout_id = result+1; return result; } diff --git a/source/libr2c2/layout.h b/source/libr2c2/layout.h index ecb801f..6ef7e09 100644 --- a/source/libr2c2/layout.h +++ b/source/libr2c2/layout.h @@ -87,7 +87,7 @@ public: void add_track(Track &); const std::set &get_tracks() const { return tracks; } void remove_track(Track &); - unsigned allocate_turnout_id(bool); + unsigned allocate_turnout_id(); void add_block(Block &); Block &get_block(unsigned) const; diff --git a/source/libr2c2/track.cpp b/source/libr2c2/track.cpp index 0592731..b157b33 100644 --- a/source/libr2c2/track.cpp +++ b/source/libr2c2/track.cpp @@ -25,11 +25,14 @@ Track::Track(Layout &l, const TrackType &t): rot(0), slope(0), flex(false), - turnout_id(type.is_turnout() ? layout.allocate_turnout_id(type.is_double_address()) : 0), + turnout_id(0), sensor_id(0), links(type.get_endpoints().size()), active_path(0) { + if(type.is_turnout()) + turnout_id = layout.allocate_turnout_id(); + layout.add_track(*this); if(layout.has_driver()) @@ -126,11 +129,7 @@ void Track::set_turnout_id(unsigned i) layout.create_blocks(*this); layout.update_routes(); if(layout.has_driver() && turnout_id) - { - layout.get_driver().add_turnout(turnout_id); - if(type.is_double_address()) - layout.get_driver().add_turnout(turnout_id+1); - } + layout.get_driver().add_turnout(turnout_id, type); } void Track::set_sensor_id(unsigned i) @@ -151,11 +150,7 @@ void Track::set_active_path(unsigned p) if(!(type.get_paths()&(1<2) - active_path = (active_path&1) | (p&2); + layout.get_driver().set_turnout(turnout_id, p); } int Track::get_endpoint_by_link(Track &other) const @@ -347,19 +342,16 @@ void Track::save(list &st) const st.push_back((DataFile::Statement("flex"), true)); } -void Track::turnout_event(unsigned addr, bool state) +void Track::turnout_event(unsigned addr, unsigned state) { if(!turnout_id) return; if(addr==turnout_id) - active_path = (active_path&2) | (state ? 1 : 0); - else if(type.is_double_address() && addr==turnout_id+1) - active_path = (active_path&1) | (state ? 2 : 0); - else - return; - - signal_path_changed.emit(active_path); + { + active_path = state; + signal_path_changed.emit(active_path); + } } diff --git a/source/libr2c2/track.h b/source/libr2c2/track.h index 95f9023..6747ed7 100644 --- a/source/libr2c2/track.h +++ b/source/libr2c2/track.h @@ -90,7 +90,7 @@ public: void save(std::list &) const; private: - void turnout_event(unsigned, bool); + void turnout_event(unsigned, unsigned); }; } // namespace R2C2 diff --git a/source/libr2c2/tracktype.cpp b/source/libr2c2/tracktype.cpp index 4ac0967..1679dc3 100644 --- a/source/libr2c2/tracktype.cpp +++ b/source/libr2c2/tracktype.cpp @@ -15,7 +15,7 @@ namespace R2C2 { TrackType::TrackType(const ArticleNumber &an): art_nr(an), - double_address(false), + state_bits(0), autofit_preference(1) { } @@ -171,11 +171,12 @@ TrackType::Endpoint::Endpoint(float x, float y, float d, unsigned p): TrackType::Loader::Loader(TrackType &t): - Msp::DataFile::BasicLoader(t) + Msp::DataFile::BasicLoader(t), + state_bits_set(false) { add("autofit_preference", &TrackType::autofit_preference); add("description", &TrackType::description); - add("double_address", &TrackType::double_address); + add("state_bits", &Loader::state_bits); add("part", &Loader::part); } @@ -189,6 +190,15 @@ void TrackType::Loader::part() TrackPart p; load_sub(p); obj.parts.push_back(p); + if(!state_bits_set && p.get_path()) + while(p.get_path()>=(1U< { + private: + bool state_bits_set; + public: Loader(TrackType &); private: virtual void finish(); void part(); void position(float, float, float); + void state_bits(unsigned); }; private: @@ -42,7 +46,7 @@ private: std::string description; std::vector parts; std::vector endpoints; - bool double_address; + unsigned state_bits; unsigned autofit_preference; public: @@ -54,9 +58,9 @@ public: float get_path_length(int) const; unsigned get_paths() const; unsigned get_n_paths() const; + unsigned get_state_bits() const { return state_bits; } bool is_turnout() const; bool is_dead_end() const; - bool is_double_address() const { return double_address; } unsigned get_autofit_preference() const { return autofit_preference; } const std::vector &get_parts() const { return parts; } const std::vector &get_endpoints() const { return endpoints; } diff --git a/source/libr2c2/train.cpp b/source/libr2c2/train.cpp index 0cbe306..2897683 100644 --- a/source/libr2c2/train.cpp +++ b/source/libr2c2/train.cpp @@ -76,7 +76,7 @@ Train::Train(Layout &l, const VehicleType &t, unsigned a, const string &p): layout.add_train(*this); - layout.get_driver().add_loco(address, protocol); + layout.get_driver().add_loco(address, protocol, loco_type); layout.get_driver().signal_loco_speed.connect(sigc::mem_fun(this, &Train::loco_speed_event)); layout.get_driver().signal_loco_function.connect(sigc::mem_fun(this, &Train::loco_func_event)); @@ -186,10 +186,7 @@ void Train::set_function(unsigned func, bool state) { if(!loco_type.get_functions().count(func)) throw InvalidParameterValue("Invalid function"); - if(func<5) - layout.get_driver().set_loco_function(address, func, state); - else - layout.get_driver().set_loco_function(address+1, func-4, state); + layout.get_driver().set_loco_function(address, func, state); } float Train::get_control(const string &ctrl) const @@ -690,10 +687,8 @@ void Train::loco_speed_event(unsigned addr, unsigned speed, bool) void Train::loco_func_event(unsigned addr, unsigned func, bool state) { - if(addr==address || (addr==address+1 && loco_type.get_max_function()>4)) + if(addr==address) { - if(addr==address+1) - func += 4; if(state) functions |= 1<