]> git.tdb.fi Git - r2c2.git/commitdiff
Framework for supporting multiple control protocols in a single driver
authorMikko Rasa <tdb@tdb.fi>
Fri, 12 Nov 2010 22:00:23 +0000 (22:00 +0000)
committerMikko Rasa <tdb@tdb.fi>
Fri, 12 Nov 2010 22:00:23 +0000 (22:00 +0000)
source/engineer/trainproperties.cpp
source/engineer/trainproperties.h
source/libmarklin/driver.h
source/libmarklin/dummy.cpp
source/libmarklin/dummy.h
source/libmarklin/intellibox.cpp
source/libmarklin/intellibox.h
source/libmarklin/layout.cpp
source/libmarklin/layout.h
source/libmarklin/train.cpp
source/libmarklin/train.h

index bf0b270ca3de41556e3219fd81ea3ee73f70dc71..e574925f259628e7846a692a34ee9dd29069e12b 100644 (file)
@@ -8,6 +8,7 @@ Distributed under the GPL
 #include <msp/gltk/label.h>
 #include <msp/strings/formatter.h>
 #include <msp/strings/lexicalcast.h>
+#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<unsigned>(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());
index 99a0e99570f2f12a6cc1d44157be433bbc75d916..465154d2948789734672233ad7b0f39d8766978f 100644 (file)
@@ -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;
index cfee532639b52688cf74f2dbd014f97a652680f8..f8d8f9c4e1d576b381830001fe5ac889f2aaec09 100644 (file)
@@ -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;
index b8478a2fe95c10e7f27843a531f658f26df72c04..da6c5c97cb630874db1889afcbd0476365016b7f 100644 (file)
@@ -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];
index 239573127fe22592c0efb57181eeb1a94bb68a64..7485fa59e2cd5baee2ab97c42cd5351a5bd9db4a 100644 (file)
@@ -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);
index 416d02184e9564836361da811ef247a4777a0f3c..bbe6781cd6b85d8090c3ed534989dec4460e4713 100644 (file)
@@ -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;
index c5c7e7af031e4761bd9fbc2fd1dbaef8853167e4..565d3cbd1e23f9bb249f9a9289c389282a31f443 100644 (file)
@@ -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);
index 25568d6e6fb23d51e86ad003cf36d12c466314b9..5f590dbb9a762473c9daa279356ddafe49061ffe 100644 (file)
@@ -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<void (Loader::*)(const string &)>(&Loader::route));
        add("track", static_cast<void (Loader::*)(unsigned)>(&Loader::track));
        add("track", static_cast<void (Loader::*)(ArticleNumber)>(&Loader::track));
-       add("train", static_cast<void (Loader::*)(unsigned, unsigned)>(&Loader::train));
-       add("train", static_cast<void (Loader::*)(ArticleNumber, unsigned)>(&Loader::train));
+       add("train", static_cast<void (Loader::*)(unsigned, unsigned, const std::string &)>(&Loader::train));
+       add("train", static_cast<void (Loader::*)(ArticleNumber, unsigned, const std::string &)>(&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);
 }
 
index 1ec1012c431d098c9ef1078fa621b2302f8bd53f..2fc761aebb4aa972c020105e62a7bc626f6d346e 100644 (file)
@@ -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:
index d9bade7dca338c5f20a53ca2624f53f2d4420298..0084f38fab8d4764c79c15873134b9f4a31d3049 100644 (file)
@@ -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<DataFile::Statement> &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; i<real_speed.size(); ++i)
                if(real_speed[i].weight)
                        st.push_back((DataFile::Statement("real_speed"), i, real_speed[i].speed, real_speed[i].weight));
 
@@ -646,7 +651,7 @@ void Train::loco_speed_event(unsigned addr, unsigned speed, bool)
 {
        if(addr==address)
        {
-               current_speed = speed;
+               current_speed_step = speed;
                speed_changing = false;
                pure_speed = false;
        }
@@ -697,9 +702,9 @@ void Train::sensor_event(unsigned addr, bool state)
 
                        if(pure_speed)
                        {
-                               if(current_speed)
+                               if(current_speed_step>0)
                                {
-                                       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<real_speed.size(); ++high)
                if(real_speed[high].weight)
                        break;
 
@@ -1122,15 +1129,17 @@ float Train::get_real_speed(unsigned i) const
                return 0;
 }
 
-unsigned Train::find_speed(float real) const
+unsigned Train::find_speed_step(float real) const
 {
-       if(real<=real_speed[0].speed)
+       if(real_speed.size()<=1)
+               return 0;
+       if(real<=real_speed[1].speed*0.5)
                return 0;
 
        unsigned low = 0;
        unsigned high = 0;
        unsigned last = 0;
-       for(unsigned i=0; (!high && i<=14); ++i)
+       for(unsigned i=0; (!high && i<real_speed.size()); ++i)
                if(real_speed[i].weight)
                {
                        last = i;
@@ -1141,14 +1150,15 @@ unsigned Train::find_speed(float real) const
                }
        if(!high)
        {
+               unsigned limit = real_speed.size()/5;
                if(!low)
                {
                        if(real)
-                               return 3;
+                               return limit;
                        else
                                return 0;
                }
-               return min(min(static_cast<unsigned>(low*real/real_speed[low].speed), 14U), last+3);
+               return min(min(static_cast<unsigned>(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<int>(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;
 }
index 5f852564074f37b5247c29f0e04a8974e569341f..a13c422a9d8c2d35f989d2704e11447152d908f5 100644 (file)
@@ -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();