]> git.tdb.fi Git - r2c2.git/commitdiff
Allow setting sensor ID for multiple tracks at once
authorMikko Rasa <tdb@tdb.fi>
Tue, 19 May 2009 18:46:03 +0000 (18:46 +0000)
committerMikko Rasa <tdb@tdb.fi>
Tue, 19 May 2009 18:46:03 +0000 (18:46 +0000)
Support for controlling turnouts with more than 2 routes
Snap flex-tracks last when loading a layout to get them correctly snapped
Slow down trains when there's only one free sensor block ahead
Put each turnout into its own block to avoid blocking adjacent tracks

source/designer/designer.cpp
source/engineer/engineer.cpp
source/libmarklin/block.cpp
source/libmarklin/layout.cpp
source/libmarklin/trafficmanager.cpp
source/libmarklin/train.cpp
source/libmarklin/train.h
source/libmarklin/turnout.cpp
source/libmarklin/turnout.h

index 2913aea1e43ec00dff88536869259ed7e523a6b9..5a7ee62ac3f6c04a7ef2f39d0f91d0937df52300 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -385,11 +385,26 @@ void Designer::key_press(unsigned code, unsigned mod, wchar_t ch)
        }
        else if(key==Msp::Input::KEY_S)
        {
-               Track *track=selection->get_track();
-               if(selection->size()==1 && track->get_type().get_n_routes()==1)
+               const set<Track *> &tracks=selection->get_tracks();
+               bool ok=false;
+               int id=-1;
+               for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
+               {
+                       if((*i)->get_type().get_n_routes()==1)
+                               ok=true;
+                       if(static_cast<int>((*i)->get_sensor_id())!=id)
+                       {
+                               if(id==-1)
+                                       id=(*i)->get_sensor_id();
+                               else
+                                       id=-2;
+                       }
+               }
+               if(ok)
                {
                        ostringstream ss;
-                       ss<<track->get_sensor_id();
+                       if(id>=0)
+                               ss<<id;
                        input=new ::Input(*this, "Sensor ID", ss.str());
                        input->signal_cancel.connect(sigc::mem_fun(this, &Designer::input_dismiss));
                        input->signal_accept.connect(sigc::mem_fun(this, &Designer::sensor_id_accept));
@@ -654,15 +669,18 @@ void Designer::turnout_id_accept()
 
 void Designer::sensor_id_accept()
 {
-       Track *track=selection->get_track();
+       const set<Track *> &tracks=selection->get_tracks();
        unsigned id=lexical_cast<unsigned>(input->get_text());
-       track->set_sensor_id(id);
+       for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
+       {
+               (*i)->set_sensor_id(id);
 
-       Track3D &t3d=layout_3d->get_track(*track);
-       if(id)
-               t3d.set_color(GL::Color(1, 1, 0.5));
-       else
-               t3d.set_color(GL::Color(1, 1, 1));
+               Track3D &t3d=layout_3d->get_track(**i);
+               if(id)
+                       t3d.set_color(GL::Color(1, 1, 0.5));
+               else
+                       t3d.set_color(GL::Color(1, 1, 1));
+       }
 
        input_dismiss();
 }
index ea87df659d7e3a7b33ccff8ed519a866295cd993..fc6d75df5e1261c17d9cc23b60a060cf8d324f5c 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -19,6 +19,7 @@ Distributed under the GPL
 #include <msp/strings/formatter.h>
 #include <msp/strings/lexicalcast.h>
 #include <msp/strings/regex.h>
+#include "libmarklin/tracktype.h"
 #include "engineer.h"
 #include "mainpanel.h"
 #include "trainpanel.h"
@@ -315,7 +316,7 @@ void Engineer::button_press(int x, int y, unsigned btn, unsigned)
                        if(unsigned tid=track->get_track().get_turnout_id())
                        {
                                Turnout &turnout=control.get_turnout(tid);
-                               turnout.set_route(1-turnout.get_route());
+                               turnout.set_route((turnout.get_route()+1)%track->get_track().get_type().get_n_routes());
                        }
                        else if(simulate)
                        {
index a304a152d6959717e02badca31da10ef6f3cc65e..03cb2dc3fa60c259f64590ed015a58f789c11c0f 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -38,7 +38,7 @@ Block::Block(TrafficManager &tm, Track &start):
                for(unsigned i=0; i<links.size(); ++i)
                        if(links[i] && !tracks.count(links[i]))
                        {
-                               if(links[i]->get_sensor_id()==sensor_id)
+                               if(links[i]->get_sensor_id()==sensor_id && !links[i]->get_turnout_id() && !track->get_turnout_id())
                                {
                                        queue.push_back(links[i]);
                                        tracks.insert(links[i]);
@@ -100,11 +100,10 @@ int Block::traverse(unsigned epi, float *len) const
                                return i;
 
                Track *next=track->get_link(other_ep);
+               if(tracks.count(next)==0)
+                       return -1;
                track_ep=next->get_endpoint_by_link(*track);
                track=next;
-
-               if(tracks.count(track)==0)
-                       return -1;
        }
 }
 
index 470d573e871179cd90bc9a7ddacb8a83591f231b..4835f2e89bd70a7b7062710998777eb5188cea30 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -47,8 +47,21 @@ void Layout::check_links()
        for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
                (*i)->break_links();
 
+       set<Track *> flext;
        for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
-               for(set<Track *>::iterator j=i; j!=tracks.end(); ++j)
+       {
+               if((*i)->get_flex())
+                       flext.insert(*i);
+               else
+               {
+                       for(set<Track *>::iterator j=i; j!=tracks.end(); ++j)
+                               if(j!=i)
+                                       (*i)->snap_to(**j, true);
+               }
+       }
+
+       for(set<Track *>::iterator i=flext.begin(); i!=flext.end(); ++i)
+               for(set<Track *>::iterator j=tracks.begin(); j!=tracks.end(); ++j)
                        if(j!=i)
                                (*i)->snap_to(**j, true);
 }
index 9666f12a1996bb8a41a5096ce2ad6eca347ad042..4cc186bcdebafa39174bba59b9aeae857152c942 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -9,6 +9,7 @@ Distributed under the GPL
 #include <msp/time/utils.h>
 #include "control.h"
 #include "layout.h"
+#include "tracktype.h"
 #include "trafficmanager.h"
 #include "turnout.h"
 
@@ -27,7 +28,7 @@ TrafficManager::TrafficManager(Control &c, Layout &l):
        for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
        {
                if(unsigned tid=(*i)->get_turnout_id())
-                       new Turnout(control, tid);
+                       new Turnout(control, tid, (*i)->get_type().get_n_routes()>=3);
                if(unsigned sid=(*i)->get_sensor_id())
                        new Sensor(control, sid);
 
index a0943a7c76370d28a3679d24330295154e4d98e6..4974318fba6e78687b842d5e0ea5baadc2b62378 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -54,15 +54,31 @@ void Train::set_speed(unsigned speed)
                        i->block->reserve(0);
                rsv_blocks.clear();
                try_reserve=Time::TimeStamp();
+               loco.set_speed(0);
+               if(old_speed)
+                       set_status("Stopped");
+       }
+       else
+       {
+               unsigned n=reserve_more();
+               if(n==0)
+               {
+                       try_reserve=Time::now()+2*Time::sec;
+                       set_status("Blocked");
+               }
+               else if(n==1)
+               {
+                       loco.set_speed(3);
+                       try_reserve=Time::now()+2*Time::sec;
+                       set_status("Slow");
+               }
+               else
+               {
+                       loco.set_speed(speed);
+                       if(!old_speed)
+                               set_status("Traveling --- kmh");
+               }
        }
-       else if(rsv_blocks.empty() && !reserve_more())
-               return;
-
-       loco.set_speed(speed);
-       if(!old_speed && target_speed)
-               set_status("Traveling --- kmh");
-       else if(old_speed && !target_speed)
-               set_status("Stopped");
 }
 
 void Train::place(Block *block, unsigned entry)
@@ -110,12 +126,19 @@ void Train::tick(const Time::TimeStamp &t)
 {
        if(try_reserve && t>try_reserve)
        {
-               if(reserve_more() || !rsv_blocks.empty())
+               unsigned n=reserve_more();
+               if(n>=2)
                {
                        loco.set_speed(target_speed);
                        set_status("Traveling --- kmh");
                        try_reserve=Time::TimeStamp();
                }
+               else if(n==1)
+               {
+                       loco.set_speed(3);
+                       set_status("Slow");
+                       try_reserve=t+2*Time::sec;
+               }
                else
                        try_reserve=t+2*Time::sec;
        }
@@ -151,19 +174,27 @@ void Train::sensor_event(bool state, Sensor *sensor)
                        cout<<"Train "<<name<<" advanced, "<<cur_blocks.size()<<" cur_blocks, "<<rsv_blocks.size()<<" rsv_blocks\n";
                }
 
-               if(target_speed && !reserve_more() && rsv_blocks.empty())
+               if(target_speed)
                {
-                       loco.set_speed(0);
-                       try_reserve=Time::now()+2*Time::sec;
-                       set_status("Blocked");
+                       unsigned n=reserve_more();
+                       if(n==0)
+                       {
+                               loco.set_speed(0);
+                               try_reserve=Time::now()+2*Time::sec;
+                               set_status("Blocked");
+                       }
+                       else if(n==1)
+                       {
+                               loco.set_speed(3);
+                               try_reserve=Time::now()+2*Time::sec;
+                               set_status("Slow");
+                       }
                }
        }
        else
        {
                cout<<"Train "<<name<<" finding blocks to free\n";
-               list<BlockRef>::iterator i;
-               for(i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
-               {
+               for(list<BlockRef>::iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
                        if(i->block->get_sensor_id()==addr)
                        {
                                ++i;
@@ -173,14 +204,13 @@ void Train::sensor_event(bool state, Sensor *sensor)
                                cur_blocks.erase(cur_blocks.begin(), i);
                                cout<<cur_blocks.size()<<" cur_blocks\n";
                        }
-               }
 
                if(target_speed)
                        reserve_more();
        }
 }
 
-bool Train::reserve_more()
+unsigned Train::reserve_more()
 {
        BlockRef *last=0;
        if(!rsv_blocks.empty())
@@ -188,13 +218,17 @@ bool Train::reserve_more()
        else if(!cur_blocks.empty())
                last=&cur_blocks.back();
        if(!last)
-               return false;
+               return 0;
 
        cout<<"Train "<<name<<" reserving more blocks\n";
 
+       unsigned nsens=0;
+       for(list<BlockRef>::const_iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
+               if(i->block->get_sensor_id())
+                       ++nsens;
+
        bool result=false;
-       unsigned size=rsv_blocks.size();
-       while(size<3)
+       while(nsens<2)
        {
                int exit=last->block->traverse(last->entry);
                if(exit>=0) 
@@ -204,8 +238,11 @@ bool Train::reserve_more()
                        {
                                rsv_blocks.push_back(BlockRef(link, link->get_endpoint_by_link(*last->block)));
                                last=&rsv_blocks.back();
-                               ++size;
-                               result=true;
+                               if(last->block->get_sensor_id())
+                               {
+                                       ++nsens;
+                                       result=true;
+                               }
                        }
                        else
                                break;
@@ -214,9 +251,19 @@ bool Train::reserve_more()
                        break;
        }
 
+       while(last && !last->block->get_sensor_id())
+       {
+               last->block->reserve(0);
+               rsv_blocks.erase(--rsv_blocks.end());
+               if(!rsv_blocks.empty())
+                       last=&rsv_blocks.back();
+               else
+                       last=0;
+       }
+
        cout<<"  "<<rsv_blocks.size()<<" rsv_blocks\n";
 
-       return result;
+       return nsens;
 }
 
 void Train::set_status(const string &s)
index a27ff8e216f6bb0eda42b46d23c22cd9ef56e5e1..43ee84dc5cd6c590e7d7a69a16dfe0eb0f3cf982 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -58,7 +58,7 @@ public:
        void tick(const Msp::Time::TimeStamp &);
 private:
        void sensor_event(bool, Sensor *);
-       bool reserve_more();
+       unsigned reserve_more();
        void set_status(const std::string &);
 };
 
index 30793fcff5727a6aed56e9aa697b02a4bbff0823..63687cf9af1bb2a29960aeb53a486cc929d1d4c4 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -18,10 +18,11 @@ using namespace Msp;
 
 namespace Marklin {
 
-Turnout::Turnout(Control &c, unsigned a):
+Turnout::Turnout(Control &c, unsigned a, bool d):
        control(c),
        addr(a),
-       route(0)
+       route(0),
+       dual(d)
 {
        control.add_turnout(*this);
 
@@ -30,7 +31,13 @@ Turnout::Turnout(Control &c, unsigned a):
        unsigned char data[2];
        data[0]=addr&0xFF;
        data[1]=(addr>>8)&0xFF;
-       control.command(CMD_TURNOUT_STATUS, data, 2).signal_done.connect(sigc::mem_fun(this, &Turnout::status_reply));
+       control.command(CMD_TURNOUT_STATUS, data, 2).signal_done.connect(sigc::bind(sigc::mem_fun(this, &Turnout::status_reply), false));
+       if(dual)
+       {
+               data[0]=(addr+1)&0xFF;
+               data[1]=((addr+1)>>8)&0xFF;
+               control.command(CMD_TURNOUT_STATUS, data, 2).signal_done.connect(sigc::bind(sigc::mem_fun(this, &Turnout::status_reply), true));
+       }
 }
 
 void Turnout::set_route(unsigned r)
@@ -47,15 +54,23 @@ void Turnout::command(bool on)
 {
        unsigned char data[2];
        data[0]=addr&0xFF;
-       data[1]=((addr>>8)&0x7) | (on ? 0x40 : 0) | (route==0 ? 0x80 : 0);
+       data[1]=((addr>>8)&0x7) | (on ? 0x40 : 0) | (route&1 ? 0 : 0x80);
        control.command(CMD_TURNOUT, data, 2);
+       if(dual)
+       {
+               data[0]=(addr+1)&0xFF;
+               data[1]=(((addr+1)>>8)&0x7) | (on ? 0x40 : 0) | (route&2 ? 0 : 0x80);
+               control.command(CMD_TURNOUT, data, 2);
+       }
 }
 
-void Turnout::status_reply(const Reply &reply)
+void Turnout::status_reply(const Reply &reply, bool high)
 {
        if(reply.get_error()==ERR_NO_ERROR)
        {
-               route=(reply.get_data()[0]&0x04) ? 0 : 1;
+               bool v=!(reply.get_data()[0]&0x04);
+               unsigned b=(high?2:1);
+               route=(route&~b)|(v?b:0);
                signal_route_changed.emit(route);
        }
 }
@@ -69,9 +84,14 @@ bool Turnout::switch_timeout()
 
 void Turnout::turnout_event(unsigned a, bool r)
 {
-       if(a==addr && r!=route)
+       if(a==addr && r!=(route&1))
+       {
+               route=(route&2)|(r?1:0);
+               signal_route_changed.emit(route);
+       }
+       else if(dual && a==addr+1 && r!=((route>>1)&1))
        {
-               route=r;
+               route=(route&1)|(r?2:0);
                signal_route_changed.emit(route);
        }
 }
index 82b50d5c05e482019da642278ba43a79bce19f9d..ae6865406523007285bf34ba561ae55105b1375a 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -25,18 +25,19 @@ private:
        Control  &control;
        unsigned addr;
        unsigned route;
+       bool     dual;
 
 public:
        sigc::signal<void, unsigned> signal_route_changed;
 
-       Turnout(Control &, unsigned);
+       Turnout(Control &, unsigned, bool =false);
 
        void     set_route(unsigned);
        unsigned get_address() const { return addr; }
        unsigned get_route() const   { return route; }
 private:
        void command(bool);
-       void status_reply(const Reply &);
+       void status_reply(const Reply &, bool);
        bool switch_timeout();
        void turnout_event(unsigned, bool);
 };