/* $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
*/
}
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));
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();
}
/* $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
*/
#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"
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)
{
/* $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
*/
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]);
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;
}
}
/* $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
*/
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);
}
/* $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
*/
#include <msp/time/utils.h>
#include "control.h"
#include "layout.h"
+#include "tracktype.h"
#include "trafficmanager.h"
#include "turnout.h"
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);
/* $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
*/
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)
{
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;
}
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;
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())
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)
{
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;
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)
/* $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
*/
void tick(const Msp::Time::TimeStamp &);
private:
void sensor_event(bool, Sensor *);
- bool reserve_more();
+ unsigned reserve_more();
void set_status(const std::string &);
};
/* $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
*/
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);
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)
{
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);
}
}
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);
}
}
/* $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
*/
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);
};