+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
#include <fcntl.h>
#include <termios.h>
#include <sys/poll.h>
#include <iostream>
-#include <msp/core/error.h>
+#include <msp/core/except.h>
#include <msp/time/units.h>
#include <msp/time/utils.h>
#include "command.h"
debug(false)
{ }
+Control::~Control()
+{
+ for(map<unsigned, Sensor *>::iterator i=sensors.begin(); i!=sensors.end(); ++i)
+ delete i->second;
+ for(map<unsigned, Turnout *>::iterator i=turnouts.begin(); i!=turnouts.end(); ++i)
+ delete i->second;
+ for(map<unsigned, Locomotive *>::iterator i=locomotives.begin(); i!=locomotives.end(); ++i)
+ delete i->second;
+ close(serial_fd);
+}
+
void Control::set_power(bool p)
{
power=p;
command(string(1, CMD_POWER_ON));
else
command(string(1, CMD_POWER_OFF));
-}
-Turnout *Control::get_turnout(unsigned id) const
-{
- TurnoutMap::const_iterator i=turnouts.find(id);
- if(i!=turnouts.end())
- return i->second;
-
- return 0;
+ signal_power_event.emit(power);
}
-Locomotive *Control::get_locomotive(unsigned id) const
+void Control::set_debug(bool d)
{
- for(LocomotiveSeq::const_iterator i=locomotives.begin(); i!=locomotives.end(); ++i)
- if((*i)->get_address()==id)
- return *i;
- return 0;
-}
-
-Sensor *Control::get_sensor(unsigned id) const
-{
- SensorMap::const_iterator i=sensors.find(id);
- if(i!=sensors.end())
- return i->second;
-
- return 0;
+ debug=d;
}
void Control::open(const string &dev)
break;
}
}
+
if(!ok)
throw Exception("IB not detected");
+
+ command(string(1, CMD_STATUS)).signal_done.connect(sigc::mem_fun(this, &Control::status_done));
}
Command &Control::command(const string &cmd)
return queue.back();
}
-void Control::add_turnout(Turnout *t)
+void Control::add_turnout(Turnout &t)
{
- if(turnouts.count(t->get_address())==0)
- turnouts.insert(TurnoutMap::value_type(t->get_address(), t));
+ turnouts[t.get_address()]=&t;
}
-void Control::add_locomotive(Locomotive *l)
+Turnout &Control::get_turnout(unsigned id) const
{
- if(find(locomotives.begin(), locomotives.end(), l)==locomotives.end())
- locomotives.push_back(l);
+ map<unsigned, Turnout *>::const_iterator i=turnouts.find(id);
+ if(i==turnouts.end())
+ throw KeyError("Unknown turnout");
+
+ return *i->second;
}
-void Control::add_sensor(Sensor *s)
+void Control::add_locomotive(Locomotive &l)
{
- if(sensors.count(s->get_address())==0)
- {
- sensors.insert(SensorMap::value_type(s->get_address(), s));
- poll_sensors=true;
- }
+ locomotives[l.get_address()]=&l;
+}
+
+Locomotive &Control::get_locomotive(unsigned id) const
+{
+ map<unsigned, Locomotive *>::const_iterator i=locomotives.find(id);
+ if(i==locomotives.end())
+ throw KeyError("Unknown locomotive");
+
+ return *i->second;
+}
+
+void Control::add_sensor(Sensor &s)
+{
+ sensors[s.get_address()]=&s;
+ poll_sensors=true;
+}
+
+Sensor &Control::get_sensor(unsigned id) const
+{
+ map<unsigned, Sensor *>::const_iterator i=sensors.find(id);
+ if(i==sensors.end())
+ throw KeyError("Unknown sensor");
+
+ return *i->second;
}
void Control::tick()
{
const Time::TimeStamp t=Time::now();
+ for(map<unsigned, Sensor *>::const_iterator i=sensors.begin(); i!=sensors.end(); ++i)
+ i->second->tick();
+
+ timer.tick(false);
+
if(t>next_event_query)
{
- next_event_query=t+300*Time::msec;
+ next_event_query=t+200*Time::msec;
command(string(1, CMD_EVENT)).signal_done.connect(sigc::mem_fun(this, &Control::event_query_done));
}
poll_sensors=false;
}
- if(queue.size() && queue.front().get_sent())
+ if(!queue.empty() && queue.front().get_sent())
{
pollfd pfd={serial_fd, POLLIN, 0};
if(poll(&pfd, 1, 0)>0)
{
- string resp=read_reply((Cmd)(unsigned char)queue.front().get_command()[0]);
+ string resp=read_reply(static_cast<Cmd>(static_cast<unsigned char>(queue.front().get_command()[0])));
if(debug)
{
printf("read: ");
for(unsigned i=0; i<resp.size(); ++i)
- printf("%02X ", (unsigned char)resp[i]);
+ printf("%02X ", static_cast<unsigned char>(resp[i]));
printf("(%d bytes)\n", resp.size());
}
- queue.front().signal_done.emit((Error)resp[0], resp.substr(1));
+ queue.front().signal_done.emit(static_cast<Error>(resp[0]), resp.substr(1));
queue.erase(queue.begin());
}
else
return;
}
- if(queue.size())
+ if(!queue.empty())
{
string cmd=queue.front().get_command();
{
printf("write: ");
for(unsigned i=0; i<cmd.size(); ++i)
- printf("%02X ",(unsigned char)cmd[i]);
- printf("(%d bytes)\n",cmd.size());
+ printf("%02X ", static_cast<unsigned char>(cmd[i]));
+ printf("(%d bytes)\n", cmd.size());
}
write(serial_fd, cmd.data(), cmd.size());
}
}
-Control::~Control()
+Time::Timer::Slot &Control::set_timer(const Time::TimeDelta &dt)
{
- close(serial_fd);
+ return timer.add(dt);
}
-/*** private ***/
-
void Control::read_all(int fd, char *buf, int size)
{
int pos=0;
}
else
{
+ if(cmd==CMD_STATUS)
+ result+=ERR_NO_ERROR;
+
unsigned expected_bytes=1;
if(cmd==CMD_FUNC_STATUS || cmd==CMD_TURNOUT_STATUS)
expected_bytes=2;
return result;
}
+void Control::status_done(Error, const string &resp)
+{
+ power=((resp[0]&0x08)!=0);
+ signal_power_event.emit(power);
+}
+
void Control::event_query_done(Error, const string &resp)
{
if(resp[0]&0x20)
command(string(1, CMD_EVENT_TURNOUT)).signal_done.connect(sigc::mem_fun(this, &Control::turnout_event_done));
if(resp[0]&0x04)
command(string(1, CMD_EVENT_SENSOR)).signal_done.connect(sigc::mem_fun(this, &Control::sensor_event_done));
+ if(resp.size()>1 && (resp[1]&0x40))
+ command(string(1, CMD_STATUS)).signal_done.connect(sigc::mem_fun(this, &Control::status_done));
}
void Control::turnout_event_done(Error, const string &resp)
unsigned count=resp[0];
for(unsigned i=0; i<count; ++i)
{
- unsigned addr=(unsigned char)resp[i*2+1]+((resp[i*2+2]&7)<<8);
+ unsigned addr=static_cast<unsigned char>(resp[i*2+1])+((resp[i*2+2]&7)<<8);
bool status=!(resp[i*2+2]&0x80);
cout<<"Turnout "<<addr<<", status "<<status<<'\n';
signal_turnout_event.emit(addr, status);
{
for(unsigned i=0; resp[i]; i+=3)
{
- unsigned module=(unsigned char)resp[i];
+ unsigned module=static_cast<unsigned char>(resp[i]);
+
cout<<"S88 module "<<module<<", status ";
for(unsigned j=0; j<16; ++j)
- {
- bool status=(resp[i+1+j/8]>>(7-j%8))&1;
- cout<<status;
- signal_sensor_event.emit(module*16+j-15, status);
- }
+ cout<<((resp[i+1+j/8]>>(7-j%8))&1);
cout<<'\n';
+
+ for(unsigned j=0; j<16; ++j)
+ signal_sensor_event.emit(module*16+j-15, (resp[i+1+j/8]>>(7-j%8))&1);
}
}