]> git.tdb.fi Git - r2c2.git/blobdiff - source/libmarklin/control.cpp
Add Id tags and copyright notices to files
[r2c2.git] / source / libmarklin / control.cpp
index 0ce16f088740524490e2f891b3d62561f588a309..ecf10348a7890a890bdc155b8ff66f04563baf14 100644 (file)
@@ -1,8 +1,15 @@
+/* $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"
@@ -21,6 +28,17 @@ Control::Control():
        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;
@@ -28,32 +46,13 @@ void Control::set_power(bool 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;
-}
 
-Locomotive *Control::get_locomotive(unsigned id) const
-{
-       for(LocomotiveSeq::const_iterator i=locomotives.begin(); i!=locomotives.end(); ++i)
-               if((*i)->get_address()==id)
-                       return *i;
-       return 0;
+       signal_power_event.emit(power);
 }
 
-Sensor *Control::get_sensor(unsigned id) const
+void Control::set_debug(bool d)
 {
-       SensorMap::const_iterator i=sensors.find(id);
-       if(i!=sensors.end())
-               return i->second;
-       
-       return 0;
+       debug=d;
 }
 
 void Control::open(const string &dev)
@@ -104,8 +103,11 @@ 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)
@@ -114,34 +116,61 @@ Command &Control::command(const string &cmd)
        return queue.back();
 }
 
-void Control::add_turnout(Turnout *t)
+void Control::add_turnout(Turnout &t)
+{
+       turnouts[t.get_address()]=&t;
+}
+
+Turnout &Control::get_turnout(unsigned id) const
 {
-       if(turnouts.count(t->get_address())==0)
-               turnouts.insert(TurnoutMap::value_type(t->get_address(), t));
+       map<unsigned, Turnout *>::const_iterator i=turnouts.find(id);
+       if(i==turnouts.end())
+               throw KeyError("Unknown turnout");
+
+       return *i->second;
 }
 
-void Control::add_locomotive(Locomotive *l)
+void Control::add_locomotive(Locomotive &l)
 {
-       if(find(locomotives.begin(), locomotives.end(), l)==locomotives.end())
-               locomotives.push_back(l);
+       locomotives[l.get_address()]=&l;
 }
 
-void Control::add_sensor(Sensor *s)
+Locomotive &Control::get_locomotive(unsigned id) const
 {
-       if(sensors.count(s->get_address())==0)
-       {
-               sensors.insert(SensorMap::value_type(s->get_address(), s));
-               poll_sensors=true;
-       }
+       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));
        }
 
@@ -157,28 +186,28 @@ void Control::tick()
                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();
 
@@ -194,8 +223,8 @@ void Control::tick()
                {
                        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());
@@ -203,19 +232,11 @@ void Control::tick()
        }
 }
 
-Control::~Control()
+Time::Timer::Slot &Control::set_timer(const Time::TimeDelta &dt)
 {
-       for(SensorMap::iterator i=sensors.begin(); i!=sensors.end(); ++i)
-               delete i->second;
-       for(TurnoutMap::iterator i=turnouts.begin(); i!=turnouts.end(); ++i)
-               delete i->second;
-       for(LocomotiveSeq::iterator i=locomotives.begin(); i!=locomotives.end(); ++i)
-               delete *i;
-       close(serial_fd);
+       return timer.add(dt);
 }
 
-/*** private ***/
-
 void Control::read_all(int fd, char *buf, int size)
 {
        int pos=0;
@@ -274,6 +295,9 @@ string Control::read_reply(Cmd cmd)
        }
        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;
@@ -296,12 +320,20 @@ string Control::read_reply(Cmd cmd)
        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)
@@ -309,7 +341,7 @@ 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);
@@ -320,15 +352,15 @@ void Control::sensor_event_done(Error, const string &resp)
 {
        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);
        }
 }