X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibr2c2%2Farducontrol.cpp;h=98f74338285178ecb73a11e63faa005deea56f6e;hb=617dacc52b5610a9ea7774cb2ca1144e9011b931;hp=fa95a6936be746bd6e2d4ee4ff3244986a5d4574;hpb=5bc94d60a17039dfd5d46caaa292d3667fa87fb3;p=r2c2.git diff --git a/source/libr2c2/arducontrol.cpp b/source/libr2c2/arducontrol.cpp index fa95a69..98f7433 100644 --- a/source/libr2c2/arducontrol.cpp +++ b/source/libr2c2/arducontrol.cpp @@ -23,7 +23,9 @@ ArduControl::ArduControl(const Options &opts): debug(opts.get("debug")), state_file("arducontrol.state"), power(false), + halted(false), active_accessory(0), + command_timeout(200*Time::msec), s88(*this), mfx_search(*this), thread(*this) @@ -67,8 +69,19 @@ void ArduControl::set_power(bool p) } } -void ArduControl::halt(bool) +void ArduControl::halt(bool h) { + if(h==halted) + return; + + halted = h; + if(halted) + { + for(LocomotiveMap::const_iterator i=locomotives.begin(); i!=locomotives.end(); ++i) + set_loco_speed(i->first, 0); + } + + signal_halt.emit(halted); } const char *ArduControl::enumerate_protocols(unsigned i) const @@ -146,6 +159,9 @@ void ArduControl::set_loco_speed(unsigned id, unsigned speed) if(speed>protocol_info[loco.proto].max_speed) throw invalid_argument("ArduControl::set_loco_speed"); + if(speed && halted) + return; + if(loco.speed.set(speed)) { PendingCommand cmd(loco, Locomotive::SPEED); @@ -389,7 +405,7 @@ void ArduControl::tick() } } - while(!active_accessory && !accessory_queue.empty()) + while(power && !active_accessory && !accessory_queue.empty()) { Accessory &acc = *accessory_queue.front(); @@ -441,6 +457,8 @@ void ArduControl::tick() void ArduControl::flush() { + while(!command_queue.empty() || (power && !accessory_queue.empty())) + tick(); } void ArduControl::save_state() const @@ -642,6 +660,12 @@ bool ArduControl::Queue::pop(T &item) return true; } +template +bool ArduControl::Queue::empty() const +{ + return items.empty(); +} + ArduControl::RefreshTask::RefreshTask(): next(cycle.end()), @@ -1001,10 +1025,41 @@ void ArduControl::ControlThread::main() if(get_work(cmd)) { bool success = true; + bool resync = false; for(unsigned i=0; (success && i=1) + IO::print("Synchronization with ArduControl lost, attempting to recover\n"); + for(unsigned i=0; (resync && i<16); ++i) + { + control.serial.put('\xFF'); + while(IO::poll(control.serial, IO::P_INPUT, control.command_timeout)) + resync = (control.serial.get()!=0xFF); + } + if(resync) + { + if(control.debug>=1) + IO::print("Resynchronization failed, giving up\n"); + done = true; + } + else + { + if(control.debug>=1) + IO::print("Resynchronization successful\n"); + if(cmd.tag) + control.command_queue.push(cmd); + } + } } else Time::sleep(10*Time::msec); @@ -1051,11 +1106,11 @@ void ArduControl::ControlThread::init_baud_rate() cmd.command[1] = rates[0]>>8; cmd.command[2] = rates[0]; cmd.length = 3; - if(do_command(cmd)==COMMAND_OK) + if(do_command(cmd, Time::sec)==COMMAND_OK) { control.serial.set_baud_rate(rates[0]); Time::sleep(Time::sec); - if(do_command(cmd)==COMMAND_OK) + if(do_command(cmd, Time::sec)==COMMAND_OK) { if(control.debug>=1) IO::print("Rate changed to %d bits/s\n", rates[0]); @@ -1083,7 +1138,7 @@ bool ArduControl::ControlThread::get_work(PendingCommand &cmd) return true; } -unsigned ArduControl::ControlThread::do_command(const PendingCommand &cmd) +unsigned ArduControl::ControlThread::do_command(const PendingCommand &cmd, const Time::TimeDelta &timeout) { if(control.debug>=2) { @@ -1103,7 +1158,7 @@ unsigned ArduControl::ControlThread::do_command(const PendingCommand &cmd) if(result) got_data = IO::poll(control.serial, IO::P_INPUT, Time::zero); else - got_data = IO::poll(control.serial, IO::P_INPUT); + got_data = IO::poll(control.serial, IO::P_INPUT, timeout); if(!got_data) break; @@ -1118,7 +1173,11 @@ unsigned ArduControl::ControlThread::do_command(const PendingCommand &cmd) char reply[15]; unsigned pos = 0; while(pos=2) {