3 This file is part of the MSP Märklin suite
4 Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa
5 Distributed under the GPL
8 #include <msp/time/timer.h>
9 #include <msp/time/units.h>
20 Turnout::Turnout(Control &c, unsigned a, bool d):
29 control.add_turnout(*this);
31 control.signal_turnout_event.connect(sigc::mem_fun(this, &Turnout::turnout_event));
33 unsigned char data[2];
35 data[1] = (addr>>8)&0xFF;
36 control.command(CMD_TURNOUT_STATUS, data, 2).signal_done.connect(sigc::bind(sigc::mem_fun(this, &Turnout::status_reply), 1));
39 data[0] = (addr+1)&0xFF;
40 data[1] = ((addr+1)>>8)&0xFF;
41 control.command(CMD_TURNOUT_STATUS, data, 2).signal_done.connect(sigc::bind(sigc::mem_fun(this, &Turnout::status_reply), 2));
45 void Turnout::set_path(unsigned char p)
47 if(path==p || pending_cmds)
50 signal_path_changing.emit(p);
57 void Turnout::command(unsigned char mask)
59 unsigned char data[2];
63 data[1] = ((addr>>8)&0x7) | (on ? 0x40 : 0) | (pending_path&1 ? 0 : 0x80);
64 control.command(CMD_TURNOUT, data, 2).signal_done.connect(sigc::bind(sigc::mem_fun(this, &Turnout::command_reply), 1));
69 data[0] = (addr+1)&0xFF;
70 data[1] = (((addr+1)>>8)&0x7) | (on ? 0x40 : 0) | (pending_path&2 ? 0 : 0x80);
71 control.command(CMD_TURNOUT, data, 2).signal_done.connect(sigc::bind(sigc::mem_fun(this, &Turnout::command_reply), 2));
76 void Turnout::command_reply(const Reply &reply, unsigned char bit)
79 if(reply.get_error()==ERR_NO_ERROR)
81 if(on && !pending_cmds)
85 control.set_timer(500*Time::msec).signal_timeout.connect(
86 sigc::bind_return(sigc::bind(sigc::mem_fun(this, &Turnout::command), 3), false));
87 signal_path_changed.emit(path);
90 else if(reply.get_error()==ERR_NO_I2C_SPACE)
92 control.set_timer(100*Time::msec).signal_timeout.connect(
93 sigc::bind_return(sigc::bind(sigc::mem_fun(this, &Turnout::command), bit), false));
97 void Turnout::status_reply(const Reply &reply, unsigned char bit)
99 if(reply.get_error()==ERR_NO_ERROR)
101 bool v = !(reply.get_data()[0]&0x04);
102 path = (path&~bit)|(v?bit:0);
103 signal_path_changed.emit(path);
107 void Turnout::turnout_event(unsigned a, bool p)
109 if(a==addr && p!=(path&1))
111 path = (path&2)|(p?1:0);
112 signal_path_changed.emit(path);
114 else if(dual && a==addr+1 && p!=((path>>1)&1))
116 path = (path&1)|(p?2:0);
117 signal_path_changed.emit(path);
121 } // namespace Marklin