X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibr2c2%2Fintellibox.cpp;h=4e6bb763d7e278a745a16fc200cfb8cdf406da63;hb=ce8be590703fdc0709863f0ee9695f40b6adb200;hp=9ac448e466108f3e964ffc6b6f6bbd9151566faf;hpb=1ff06c5bc46a677fa389ef86c6b26664368f1653;p=r2c2.git diff --git a/source/libr2c2/intellibox.cpp b/source/libr2c2/intellibox.cpp index 9ac448e..4e6bb76 100644 --- a/source/libr2c2/intellibox.cpp +++ b/source/libr2c2/intellibox.cpp @@ -12,6 +12,8 @@ Distributed under the GPL #include #include #include "intellibox.h" +#include "tracktype.h" +#include "vehicletype.h" using namespace std; using namespace Msp; @@ -96,6 +98,7 @@ void Intellibox::halt(bool h) const char *Intellibox::enumerate_protocols(unsigned i) const { + ++i; if(i==MM) return "MM"; else if(i==MM_27) @@ -113,13 +116,19 @@ unsigned Intellibox::get_protocol_speed_steps(const string &proto_name) const return 0; } -void Intellibox::add_loco(unsigned addr, const string &proto_name) +void Intellibox::add_loco(unsigned addr, const string &proto_name, const VehicleType &type) { Protocol proto = map_protocol(proto_name); if(!locos.count(addr)) { - locos[addr].protocol = proto; + Locomotive &loco = locos[addr]; + loco.protocol = proto; + if(type.get_max_function()>4) + { + loco.ext_func = true; + locos[addr+1].protocol = NONE; + } unsigned char data[2]; data[0] = addr&0xFF; @@ -131,6 +140,9 @@ void Intellibox::add_loco(unsigned addr, const string &proto_name) void Intellibox::set_loco_speed(unsigned addr, unsigned speed) { Locomotive &loco = locos[addr]; + if(loco.protocol==NONE) + return; + if(speed==loco.speed) { if(loco.pending_half_step) @@ -163,14 +175,14 @@ void Intellibox::set_loco_speed(unsigned addr, unsigned speed) loco.pending_half_step = 0; loco.half_step_delay = Time::TimeStamp(); - loco_command(addr, (speed+1)/2, loco.reverse, loco.funcs|0x100); + loco_command(addr, (speed+1)/2, loco.reverse, loco.funcs, false); } - else + else if(loco.protocol==MM) { if(speed>14) speed = 14; - loco_command(addr, speed, loco.reverse, loco.funcs|0x100); + loco_command(addr, speed, loco.reverse, loco.funcs, false); } loco.speed = speed; } @@ -178,56 +190,82 @@ void Intellibox::set_loco_speed(unsigned addr, unsigned speed) void Intellibox::set_loco_reverse(unsigned addr, bool rev) { Locomotive &loco = locos[addr]; - if(rev==loco.reverse) + if(loco.protocol==NONE || rev==loco.reverse) return; + loco.speed = 0; loco.reverse = rev; - loco_command(addr, loco.speed, rev, loco.funcs|0x100); + loco_command(addr, 0, rev, loco.funcs, false); } void Intellibox::set_loco_function(unsigned addr, unsigned func, bool state) { Locomotive &loco = locos[addr]; + if(loco.protocol==NONE) + return; + if(state) loco.funcs |= 1<>4)&0x1E, true); signal_loco_function.emit(addr, func, state); } -void Intellibox::add_turnout(unsigned addr) +void Intellibox::add_turnout(unsigned addr, const TrackType &type) { if(!turnouts.count(addr)) { - turnouts[addr]; + Turnout &turnout = turnouts[addr]; + turnout.bits = type.get_state_bits(); unsigned char data[2]; data[0] = addr&0xFF; data[1] = (addr>>8)&0xFF; command(CMD_TURNOUT_STATUS, addr, data, 2); + for(unsigned i=1; i::const_iterator i = turnouts.find(addr); if(i!=turnouts.end()) return i->second.state; - return false; + return 0; } void Intellibox::add_sensor(unsigned addr) @@ -263,7 +301,7 @@ void Intellibox::tick() i->second.speed += i->second.pending_half_step; i->second.pending_half_step = 0; i->second.half_step_delay = Time::TimeStamp(); - loco_command(i->first, (i->second.speed+1)/2, i->second.reverse, i->second.funcs|0x100); + loco_command(i->first, (i->second.speed+1)/2, i->second.reverse, i->second.funcs, false); } for(map::iterator i=turnouts.begin(); i!=turnouts.end(); ++i) @@ -271,7 +309,8 @@ void Intellibox::tick() { i->second.active = false; i->second.off_timeout = Time::TimeStamp(); - turnout_command(i->first, i->second.state, false); + for(unsigned j=0; jsecond.bits; ++j) + turnout_command(i->first+j, !(i->second.state&(1<::iterator i=sensors.begin(); i!=sensors.end(); ++i) @@ -365,7 +404,7 @@ void Intellibox::command(Command cmd, unsigned addr, const unsigned char *data, queue.push_back(slot); } -void Intellibox::loco_command(unsigned addr, unsigned speed, bool rev, unsigned funcs) +void Intellibox::loco_command(unsigned addr, unsigned speed, bool rev, unsigned funcs, bool setf) { unsigned char data[4]; data[0] = addr&0xFF; @@ -380,7 +419,7 @@ void Intellibox::loco_command(unsigned addr, unsigned speed, bool rev, unsigned data[3] = (rev ? 0 : 0x20) | ((funcs&1) ? 0x10 : 0); - if(!(funcs&0x100)) + if(setf) data[3] |= 0x80 | ((funcs>>1)&0xF); command(CMD_LOK, addr, data, 4); @@ -452,8 +491,12 @@ void Intellibox::process_reply(const Time::TimeStamp &t) read_all(data, 2); unsigned addr = data[0]+((data[1]&7)<<8); + unsigned mask = 1; + for(; !turnouts[addr].bits; --addr, mask<<=1) ; Turnout &turnout = turnouts[addr]; - turnout.state = (data[1]&0x80)!=0; + + unsigned bit = !(data[1]&0x80); + turnout.state = (turnout.state&~mask) | (bit*mask); turnout.pending = turnout.state; signal_turnout.emit(addr, turnout.state); } @@ -498,9 +541,12 @@ void Intellibox::process_reply(const Time::TimeStamp &t) { unsigned addr = queue.front().addr; Locomotive &loco = locos[addr]; - signal_loco_speed.emit(addr, loco.speed+loco.pending_half_step, loco.reverse); - if(loco.pending_half_step) - loco.half_step_delay = Time::now()+500*Time::msec; + if(loco.protocol) + { + signal_loco_speed.emit(addr, loco.speed+loco.pending_half_step, loco.reverse); + if(loco.pending_half_step) + loco.half_step_delay = Time::now()+500*Time::msec; + } } else error(cmd, err); @@ -511,14 +557,17 @@ void Intellibox::process_reply(const Time::TimeStamp &t) read_status(&err); unsigned addr = queue.front().addr; + unsigned mask = 1; + for(; !turnouts[addr].bits; --addr, mask<<=1) ; Turnout &turnout = turnouts[addr]; if(err==ERR_NO_ERROR) { - turnout.state = turnout.pending; + turnout.state = (turnout.state&~mask) | (turnout.pending&mask); if(turnout.active) { - signal_turnout.emit(addr, turnout.state); + if(turnout.state==turnout.pending) + signal_turnout.emit(addr, turnout.state); turnout.off_timeout = t+500*Time::msec; } } @@ -526,7 +575,7 @@ void Intellibox::process_reply(const Time::TimeStamp &t) queue.push_back(queue.front()); else { - turnout.pending = turnout.state; + turnout.pending = (turnout.pending&~mask) | (turnout.state&mask); error(cmd, err); } } @@ -541,15 +590,19 @@ void Intellibox::process_reply(const Time::TimeStamp &t) read_all(&data, 1); unsigned addr = queue.front().addr; - bool state = data&0x04; - + unsigned mask = 1; + for(; !turnouts[addr].bits; --addr, mask<<=1) ; Turnout &turnout = turnouts[addr]; - if(state!=turnout.state) + + bool bit = !(data&0x04); + if(bit!=((turnout.state&mask)!=0)) { - turnout.state = state; - turnout.pending = state; + turnout.state = (turnout.state&~mask) | (bit*mask); + turnout.pending = turnout.state; signal_turnout.emit(addr, turnout.state); } + + turnout.synced = true; } else error(cmd, err); @@ -569,24 +622,22 @@ void Intellibox::process_reply(const Time::TimeStamp &t) unsigned speed = (data[0]<=1 ? 0 : data[0]*2/19+1); bool reverse = !(data[1]&0x20); - if(speed!=loco.speed || reverse!=loco.reverse) - { - loco.speed = speed; - loco.reverse = reverse; - signal_loco_speed.emit(addr, loco.speed, loco.reverse); - } + bool speed_changed = (speed!=loco.speed || reverse!=loco.reverse); + + loco.speed = speed; + loco.reverse = reverse; unsigned funcs = (data[1]&0xF)<<1; if(data[1]&0x10) funcs |= 1; - if(funcs!=loco.funcs) - { - unsigned changed = loco.funcs^funcs; - loco.funcs = funcs; - for(unsigned i=0; i<5; ++i) - if(changed&(1<