--- /dev/null
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#include <msp/time/units.h>
+#include "block.h"
+#include "catalogue.h"
+#include "driver.h"
+#include "layout.h"
+#include "timetable.h"
+#include "train.h"
+
+using namespace std;
+using namespace Msp;
+
+namespace Marklin {
+
+Timetable::Timetable(Train &t):
+ train(t),
+ current_row(0),
+ executing(true),
+ pending_block(0)
+{
+ train.signal_arrived.connect(sigc::mem_fun(this, &Timetable::train_arrived));
+ train.get_layout().get_driver().signal_sensor.connect(sigc::mem_fun(this, &Timetable::sensor_event));
+}
+
+void Timetable::tick(const Time::TimeStamp &t)
+{
+ if(wait_timeout && t>=wait_timeout)
+ {
+ wait_timeout = Time::TimeStamp();
+ current_row = (current_row+1)%rows.size();
+ executing = true;
+ }
+
+ while(executing)
+ {
+ Row &row = rows[current_row];
+ switch(row.type)
+ {
+ case GOTO:
+ train.go_to(**parse_location(row.strparam).get_tracks().begin());
+ executing = false;
+ break;
+ case TRAVEL:
+ pending_block = &parse_location(row.strparam);
+ executing = false;
+ break;
+ case WAIT:
+ wait_timeout = t+row.intparam*Time::sec;
+ executing = false;
+ break;
+ case SPEED:
+ train.set_control("speed", row.intparam/3.6*train.get_layout().get_catalogue().get_scale());
+ break;
+ case ROUTE:
+ train.set_route(&train.get_layout().get_route(row.strparam));
+ break;
+ }
+
+ if(executing)
+ current_row = (current_row+1)%rows.size();
+ }
+}
+
+void Timetable::save(list<DataFile::Statement> &st) const
+{
+ for(vector<Row>::const_iterator i=rows.begin(); i!=rows.end(); ++i)
+ {
+ switch(i->type)
+ {
+ case GOTO:
+ st.push_back((DataFile::Statement("goto"), i->strparam));
+ break;
+ case TRAVEL:
+ st.push_back((DataFile::Statement("travel"), i->strparam));
+ break;
+ case WAIT:
+ st.push_back((DataFile::Statement("wait"), i->intparam));
+ break;
+ case SPEED:
+ st.push_back((DataFile::Statement("speed"), i->intparam));
+ break;
+ case ROUTE:
+ st.push_back((DataFile::Statement("route"), i->strparam));
+ break;
+ }
+ }
+}
+
+Block &Timetable::parse_location(const string &loc)
+{
+ if(!loc.compare(0, 7, "sensor "))
+ return train.get_layout().get_block(lexical_cast<unsigned>(loc.substr(7))|0x1000);
+ throw Exception("Named blocks are not supported yet");
+}
+
+void Timetable::sensor_event(unsigned addr, bool state)
+{
+ if(pending_block && pending_block->get_train()==&train && addr==pending_block->get_sensor_id() && state)
+ {
+ pending_block = 0;
+ current_row = (current_row+1)%rows.size();
+ executing = true;
+ }
+}
+
+void Timetable::train_arrived()
+{
+ Row &row = rows[current_row];
+ if(row.type==GOTO)
+ {
+ current_row = (current_row+1)%rows.size();
+ executing = true;
+ }
+}
+
+
+Timetable::Row::Row(RowType t, int p):
+ type(t),
+ intparam(p)
+{ }
+
+Timetable::Row::Row(RowType t, const string &p):
+ type(t),
+ intparam(0),
+ strparam(p)
+{ }
+
+
+Timetable::Loader::Loader(Timetable &tt):
+ DataFile::ObjectLoader<Timetable>(tt)
+{
+ add("goto", &Loader::go_to);
+ add("route", &Loader::route);
+ add("speed", &Loader::speed);
+ add("travel", &Loader::travel);
+ add("wait", &Loader::wait);
+}
+
+void Timetable::Loader::go_to(const string &t)
+{
+ obj.rows.push_back(Row(GOTO, t));
+}
+
+void Timetable::Loader::route(const string &r)
+{
+ obj.rows.push_back(Row(ROUTE, r));
+}
+
+void Timetable::Loader::speed(int s)
+{
+ obj.rows.push_back(Row(SPEED, s));
+}
+
+void Timetable::Loader::travel(const string &t)
+{
+ obj.rows.push_back(Row(TRAVEL, t));
+}
+
+void Timetable::Loader::wait(unsigned t)
+{
+ obj.rows.push_back(Row(WAIT, t));
+}
+
+} // namespace Marklin
--- /dev/null
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#ifndef LIBMARKLIN_TIMETABLE_H_
+#define LIBMARKLIN_TIMETABLE_H_
+
+#include <string>
+#include <vector>
+#include <msp/datafile/objectloader.h>
+#include <msp/time/timestamp.h>
+
+namespace Marklin {
+
+class Block;
+class Train;
+
+class Timetable
+{
+public:
+ class Loader: public Msp::DataFile::ObjectLoader<Timetable>
+ {
+ public:
+ Loader(Timetable &);
+ private:
+ void go_to(const std::string &);
+ void route(const std::string &);
+ void speed(int);
+ void travel(const std::string &);
+ void wait(unsigned);
+ };
+
+ enum RowType
+ {
+ GOTO,
+ TRAVEL,
+ WAIT,
+ SPEED,
+ ROUTE
+ };
+
+ struct Row
+ {
+ RowType type;
+ int intparam;
+ std::string strparam;
+
+ Row(RowType, int);
+ Row(RowType, const std::string &);
+ };
+
+private:
+ Train &train;
+ std::vector<Row> rows;
+ unsigned current_row;
+ bool executing;
+ Block *pending_block;
+ Msp::Time::TimeStamp wait_timeout;
+
+public:
+ Timetable(Train &);
+
+ void tick(const Msp::Time::TimeStamp &);
+ void save(std::list<Msp::DataFile::Statement> &) const;
+private:
+ Block &parse_location(const std::string &);
+ void sensor_event(unsigned, bool);
+ void train_arrived();
+};
+
+} // namespace Marklin
+
+#endif
#include "locotype.h"
#include "route.h"
#include "simplephysics.h"
+#include "timetable.h"
#include "tracktype.h"
#include "train.h"
#include "vehicle.h"
address(a),
pending_block(0),
control(new AIControl(*this, new SimplePhysics)),
+ timetable(0),
active(false),
current_speed(0),
speed_changing(false),
stop_timeout = Time::TimeStamp();
}
+ if(timetable)
+ timetable->tick(t);
control->tick(dt);
float speed = control->get_speed();
unsigned speed_notch = find_speed(abs(speed));
if(route)
st.push_back((DataFile::Statement("route"), route->get_name()));
+
+ if(timetable)
+ {
+ DataFile::Statement ss("timetable");
+ timetable->save(ss.sub);
+ st.push_back(ss);
+ }
}
void Train::loco_speed_event(unsigned addr, unsigned speed, bool)
add("name", &Loader::name);
add("real_speed", &Loader::real_speed);
add("route", &Loader::route);
+ add("timetable", &Loader::timetable);
}
void Train::Loader::block(unsigned id)
obj.set_route(&obj.layout.get_route(n));
}
+void Train::Loader::timetable()
+{
+ if(obj.timetable)
+ throw InvalidState("A timetable has already been loaded");
+
+ obj.timetable = new Timetable(obj);
+ load_sub(*obj.timetable);
+}
+
} // namespace Marklin