#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"
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;
{
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());
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;
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;
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];
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);
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;
struct Locomotive
{
+ std::string protocol;
unsigned speed;
bool reverse;
unsigned funcs;
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);
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);
}
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()
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);
}
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:
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()),
controller(new AIControl(*this, new SimpleController)),
timetable(0),
active(false),
- current_speed(0),
+ current_speed_step(0),
speed_changing(false),
reverse(false),
functions(0),
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)
{
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));
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)
{
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");
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);
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));
{
if(addr==address)
{
- current_speed = speed;
+ current_speed_step = speed;
speed_changing = false;
pure_speed = false;
}
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()));
float Train::get_real_speed(unsigned i) const
{
+ if(i==0)
+ return 0;
if(real_speed[i].weight)
return real_speed[i].speed;
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;
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;
}
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);
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;
}
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;
}
Layout &layout;
const VehicleType &loco_type;
unsigned address;
+ std::string protocol;
std::string name;
int priority;
const Train *yielding_to;
Controller *controller;
Timetable *timetable;
bool active;
- unsigned current_speed;
+ unsigned current_speed_step;
bool speed_changing;
bool reverse;
Msp::Time::TimeStamp stop_timeout;
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);
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();