From 975ea87cc7be179618b06291cb2506a2523cad1f Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 12 Nov 2010 22:00:23 +0000 Subject: [PATCH] Framework for supporting multiple control protocols in a single driver --- source/engineer/trainproperties.cpp | 16 +++++++-- source/engineer/trainproperties.h | 1 + source/libmarklin/driver.h | 4 ++- source/libmarklin/dummy.cpp | 12 +++++++ source/libmarklin/dummy.h | 4 ++- source/libmarklin/intellibox.cpp | 19 +++++++++-- source/libmarklin/intellibox.h | 5 ++- source/libmarklin/layout.cpp | 13 ++++---- source/libmarklin/layout.h | 4 +-- source/libmarklin/train.cpp | 52 ++++++++++++++++++----------- source/libmarklin/train.h | 8 +++-- 11 files changed, 100 insertions(+), 38 deletions(-) diff --git a/source/engineer/trainproperties.cpp b/source/engineer/trainproperties.cpp index bf0b270..e574925 100644 --- a/source/engineer/trainproperties.cpp +++ b/source/engineer/trainproperties.cpp @@ -8,6 +8,7 @@ Distributed under the GPL #include #include #include +#include "libmarklin/driver.h" #include "libmarklin/vehicle.h" #include "libmarklin/vehicletype.h" #include "engineer.h" @@ -30,8 +31,19 @@ TrainProperties::TrainProperties(Engineer &e, Train *t): add(*(ent_addr = new GLtk::Entry)); ent_addr->set_geometry(GLtk::Geometry(10, geom.h-50, 40, 20)); + add(*(drp_protocol = new GLtk::Dropdown)); + drp_protocol->set_geometry(GLtk::Geometry(60, geom.h-50, 60, 20)); + for(unsigned i=0;; ++i) + { + if(const char *proto = engineer.get_layout().get_driver().enumerate_protocols(i)) + drp_protocol->append(proto); + else + break; + } + drp_protocol->set_selected_index(0); + add(*(drp_type = new GLtk::Dropdown)); - drp_type->set_geometry(GLtk::Geometry(60, geom.h-50, geom.w-70, 20)); + drp_type->set_geometry(GLtk::Geometry(130, geom.h-50, geom.w-140, 20)); const Catalogue::VehicleMap &vehs = engineer.get_catalogue().get_vehicles(); unsigned n = 0; @@ -106,7 +118,7 @@ void TrainProperties::on_ok_clicked() { const VehicleType &type = get_vehicle_type(drp_type->get_selected_index(), true); unsigned addr = lexical_cast(ent_addr->get_text()); - train = new Train(engineer.get_layout(), type, addr); + train = new Train(engineer.get_layout(), type, addr, drp_protocol->get_selected()); } train->set_name(ent_name->get_text()); diff --git a/source/engineer/trainproperties.h b/source/engineer/trainproperties.h index 99a0e99..465154d 100644 --- a/source/engineer/trainproperties.h +++ b/source/engineer/trainproperties.h @@ -21,6 +21,7 @@ private: Engineer &engineer; Marklin::Train *train; Msp::GLtk::Entry *ent_addr; + Msp::GLtk::Dropdown *drp_protocol; Msp::GLtk::Dropdown *drp_type; Msp::GLtk::Entry *ent_name; Msp::GLtk::Dropdown *drp_priority; diff --git a/source/libmarklin/driver.h b/source/libmarklin/driver.h index cfee532..f8d8f9c 100644 --- a/source/libmarklin/driver.h +++ b/source/libmarklin/driver.h @@ -33,7 +33,9 @@ public: virtual void halt(bool) = 0; virtual bool is_halted() const = 0; - virtual void add_loco(unsigned) = 0; + 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 set_loco_speed(unsigned, unsigned) = 0; virtual void set_loco_reverse(unsigned, bool) = 0; virtual void set_loco_function(unsigned, unsigned, bool) = 0; diff --git a/source/libmarklin/dummy.cpp b/source/libmarklin/dummy.cpp index b8478a2..da6c5c9 100644 --- a/source/libmarklin/dummy.cpp +++ b/source/libmarklin/dummy.cpp @@ -21,6 +21,18 @@ void Dummy::set_power(bool p) signal_power.emit(power); } +const char *Dummy::enumerate_protocols(unsigned i) const +{ + if(i==0) + return "dummy"; + return 0; +} + +unsigned Dummy::get_protocol_speed_steps(const string &) const +{ + return 0; +} + void Dummy::add_turnout(unsigned addr) { turnouts[addr]; diff --git a/source/libmarklin/dummy.h b/source/libmarklin/dummy.h index 2395731..7485fa5 100644 --- a/source/libmarklin/dummy.h +++ b/source/libmarklin/dummy.h @@ -35,7 +35,9 @@ public: virtual void halt(bool) { } virtual bool is_halted() const { return false; } - virtual void add_loco(unsigned) { } + 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); diff --git a/source/libmarklin/intellibox.cpp b/source/libmarklin/intellibox.cpp index 416d021..bbe6781 100644 --- a/source/libmarklin/intellibox.cpp +++ b/source/libmarklin/intellibox.cpp @@ -94,11 +94,26 @@ void Intellibox::halt(bool h) signal_halt.emit(halted); } -void Intellibox::add_loco(unsigned addr) +const char *Intellibox::enumerate_protocols(unsigned i) const +{ + if(i==0) + return "MM"; + return 0; +} + +unsigned Intellibox::get_protocol_speed_steps(const string &proto) const +{ + if(proto=="MM") + return 14; + else + throw InvalidParameterValue("Unknown protocol"); +} + +void Intellibox::add_loco(unsigned addr, const string &proto) { if(!locos.count(addr)) { - locos[addr]; + locos[addr].protocol = proto; unsigned char data[2]; data[0] = addr&0xFF; diff --git a/source/libmarklin/intellibox.h b/source/libmarklin/intellibox.h index c5c7e7a..565d3cb 100644 --- a/source/libmarklin/intellibox.h +++ b/source/libmarklin/intellibox.h @@ -63,6 +63,7 @@ private: struct Locomotive { + std::string protocol; unsigned speed; bool reverse; unsigned funcs; @@ -115,7 +116,9 @@ public: virtual void halt(bool); virtual bool is_halted() const { return halted; } - virtual void add_loco(unsigned); + 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); diff --git a/source/libmarklin/layout.cpp b/source/libmarklin/layout.cpp index 25568d6..5f590db 100644 --- a/source/libmarklin/layout.cpp +++ b/source/libmarklin/layout.cpp @@ -269,6 +269,7 @@ void Layout::save_trains(const string &fn) DataFile::Statement st("train"); st.append(i->second->get_locomotive_type().get_article_number()); st.append(i->second->get_address()); + st.append(i->second->get_protocol()); i->second->save(st.sub); writer.write(st); } @@ -298,8 +299,8 @@ Layout::Loader::Loader(Layout &l): add("route", static_cast(&Loader::route)); add("track", static_cast(&Loader::track)); add("track", static_cast(&Loader::track)); - add("train", static_cast(&Loader::train)); - add("train", static_cast(&Loader::train)); + add("train", static_cast(&Loader::train)); + add("train", static_cast(&Loader::train)); } void Layout::Loader::finish() @@ -336,14 +337,14 @@ void Layout::Loader::track(ArticleNumber art_nr) trk->snap_to(**i, true); } -void Layout::Loader::train(unsigned art_nr, unsigned addr) +void Layout::Loader::train(unsigned art_nr, unsigned addr, const std::string &proto) { - train(ArticleNumber(art_nr), addr); + train(ArticleNumber(art_nr), addr, proto); } -void Layout::Loader::train(ArticleNumber art_nr, unsigned addr) +void Layout::Loader::train(ArticleNumber art_nr, unsigned addr, const std::string &proto) { - Train *trn = new Train(obj, obj.catalogue.get_vehicle(art_nr), addr); + Train *trn = new Train(obj, obj.catalogue.get_vehicle(art_nr), addr, proto); load_sub(*trn); } diff --git a/source/libmarklin/layout.h b/source/libmarklin/layout.h index 1ec1012..2fc761a 100644 --- a/source/libmarklin/layout.h +++ b/source/libmarklin/layout.h @@ -40,8 +40,8 @@ public: void route(const std::string &); void track(unsigned); void track(ArticleNumber); - void train(unsigned, unsigned); - void train(ArticleNumber, unsigned); + void train(unsigned, unsigned, const std::string &); + void train(ArticleNumber, unsigned, const std::string &); }; public: diff --git a/source/libmarklin/train.cpp b/source/libmarklin/train.cpp index d9bade7..0084f38 100644 --- a/source/libmarklin/train.cpp +++ b/source/libmarklin/train.cpp @@ -40,10 +40,11 @@ struct SetFlag namespace Marklin { -Train::Train(Layout &l, const VehicleType &t, unsigned a): +Train::Train(Layout &l, const VehicleType &t, unsigned a, const string &p): layout(l), loco_type(t), address(a), + protocol(p), priority(0), yielding_to(0), cur_blocks_end(blocks.end()), @@ -54,7 +55,7 @@ Train::Train(Layout &l, const VehicleType &t, unsigned a): controller(new AIControl(*this, new SimpleController)), timetable(0), active(false), - current_speed(0), + current_speed_step(0), speed_changing(false), reverse(false), functions(0), @@ -62,7 +63,7 @@ Train::Train(Layout &l, const VehicleType &t, unsigned a): status("Unplaced"), travel_dist(0), pure_speed(false), - real_speed(15), + real_speed(layout.get_driver().get_protocol_speed_steps(protocol)+1), accurate_position(false), overshoot_dist(false) { @@ -73,7 +74,7 @@ Train::Train(Layout &l, const VehicleType &t, unsigned a): layout.add_train(*this); - layout.get_driver().add_loco(address); + layout.get_driver().add_loco(address, protocol); 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)); @@ -522,7 +523,7 @@ void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) timetable->tick(t); controller->tick(dt); float speed = controller->get_speed(); - unsigned speed_notch = find_speed(speed); + unsigned speed_step = find_speed_step(speed); if(controller->get_reverse()!=reverse) { @@ -534,14 +535,14 @@ void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) reserve_more(); } - if(speed_notch!=current_speed && !speed_changing && !driver.is_halted() && driver.get_power()) + if(speed_step!=current_speed_step && !speed_changing && !driver.is_halted() && driver.get_power()) { speed_changing = true; - driver.set_loco_speed(address, speed_notch); + driver.set_loco_speed(address, speed_step); pure_speed = false; - if(speed_notch) + if(speed_step) set_status(format("Traveling %d kmh", get_travel_speed())); else set_status("Waiting"); @@ -559,7 +560,11 @@ void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) for(BlockList::const_iterator i=blocks.begin(); (!ok && i!=cur_blocks_end); ++i) ok = (*i)->has_track(*track); - float d = get_real_speed(current_speed)*(dt/Time::sec); + float d; + if(real_speed.size()>1) + d = get_real_speed(current_speed_step)*(dt/Time::sec); + else + d = speed*(dt/Time::sec); if(ok) { SetFlag setf(advancing); @@ -604,7 +609,7 @@ void Train::save(list &st) const if(i!=vehicles.begin()) st.push_back((DataFile::Statement("vehicle"), (*i)->get_type().get_article_number())); - for(unsigned i=0; i<=14; ++i) + for(unsigned i=0; i0) { - RealSpeed &rs = real_speed[current_speed]; + RealSpeed &rs = real_speed[current_speed_step]; rs.add(travel_dist/travel_time_secs, travel_time_secs); } set_status(format("Traveling %d kmh", get_travel_speed())); @@ -1094,6 +1099,8 @@ float Train::get_reserved_distance_until(const Block *until_block, bool back) co float Train::get_real_speed(unsigned i) const { + if(i==0) + return 0; if(real_speed[i].weight) return real_speed[i].speed; @@ -1102,7 +1109,7 @@ float Train::get_real_speed(unsigned i) const for(low=i; low>0; --low) if(real_speed[low].weight) break; - for(high=i; high<14; ++high) + for(high=i; high(low*real/real_speed[low].speed), 14U), last+3); + return min(min(static_cast(low*real/real_speed[low].speed), real_speed.size()-1), last+limit); } float f = (real-real_speed[low].speed)/(real_speed[high].speed-real_speed[low].speed); @@ -1157,7 +1167,7 @@ unsigned Train::find_speed(float real) const float Train::get_travel_speed() const { - float speed = get_real_speed(current_speed); + float speed = get_real_speed(current_speed_step); float scale = layout.get_catalogue().get_scale(); return static_cast(round(speed/scale*3.6/5))*5; } @@ -1379,6 +1389,8 @@ void Train::Loader::name(const string &n) void Train::Loader::real_speed(unsigned i, float speed, float weight) { + if(i>=obj.real_speed.size()) + return; obj.real_speed[i].speed = speed; obj.real_speed[i].weight = weight; } diff --git a/source/libmarklin/train.h b/source/libmarklin/train.h index 5f85256..a13c422 100644 --- a/source/libmarklin/train.h +++ b/source/libmarklin/train.h @@ -75,6 +75,7 @@ private: Layout &layout; const VehicleType &loco_type; unsigned address; + std::string protocol; std::string name; int priority; const Train *yielding_to; @@ -88,7 +89,7 @@ private: Controller *controller; Timetable *timetable; bool active; - unsigned current_speed; + unsigned current_speed_step; bool speed_changing; bool reverse; Msp::Time::TimeStamp stop_timeout; @@ -105,12 +106,13 @@ private: float overshoot_dist; public: - Train(Layout &, const VehicleType &, unsigned); + Train(Layout &, const VehicleType &, unsigned, const std::string &); ~Train(); Layout &get_layout() const { return layout; } const VehicleType &get_locomotive_type() const { return loco_type; } unsigned get_address() const { return address; } + const std::string &get_protocol() const { return protocol; } void set_name(const std::string &); const std::string &get_name() const { return name; } void set_priority(int); @@ -165,7 +167,7 @@ private: void check_turnout_paths(bool); float get_reserved_distance_until(const Block *, bool) const; float get_real_speed(unsigned) const; - unsigned find_speed(float) const; + unsigned find_speed_step(float) const; float get_travel_speed() const; void set_status(const std::string &); void release_blocks(); -- 2.45.2