}
+ArduControl::Task::Task(const string &n, unsigned p):
+ name(n),
+ priority(p)
+{ }
+
+void ArduControl::Task::sleep(const Time::TimeDelta &dt)
+{
+ sleep_timeout = Time::now()+dt;
+}
+
+
+ArduControl::CommandQueueTask::CommandQueueTask():
+ Task("CommandQueue")
+{ }
+
+
ArduControl::RefreshTask::RefreshTask():
+ Task("Refresh", 2),
next(cycle.end()),
round(0),
loco(0),
ArduControl::S88Task::S88Task(ArduControl &c):
+ Task("S88"),
control(c),
n_octets(0),
- octets_remaining(0),
- delay(0)
+ octets_remaining(0)
{ }
bool ArduControl::S88Task::get_work(PendingCommand &cmd)
{
- if(delay)
- {
- --delay;
- return false;
- }
if(octets_remaining || !n_octets)
return false;
cmd.command[1] = octets_remaining;
cmd.length = 2;
- delay = 4;
+ sleep(100*Time::msec);
return true;
}
ArduControl::MfxAnnounceTask::MfxAnnounceTask():
+ Task("MfxAnnounce", 1),
serial(0)
{ }
bool ArduControl::MfxAnnounceTask::get_work(PendingCommand &cmd)
{
- Time::TimeStamp t = Time::now();
- if(t<next)
- return false;
-
cmd.command[0] = MFX_ANNOUNCE;
cmd.command[1] = serial>>8;
cmd.command[2] = serial;
cmd.length = 3;
- next = t+400*Time::msec;
+
+ sleep(400*Time::msec);
return true;
}
ArduControl::MfxSearchTask::MfxSearchTask(ArduControl &c):
+ Task("MfxSearch", 1),
control(c),
next_address(1),
size(0),
return true;
}
- Time::TimeStamp t = Time::now();
- if(t<next)
- return false;
-
cmd.command[0] = MFX_SEARCH;
for(unsigned i=0; i<4; ++i)
cmd.command[1+i] = bits>>(24-i*8);
cmd.command[5] = size;
cmd.length = 6;
- next = t+200*Time::msec;
+ sleep(200*Time::msec);
if(control.debug>=1)
IO::print("Search %08X/%d\n", bits, size);
}
else
{
- next = Time::now()+2*Time::sec;
+ sleep(2*Time::sec);
bits = 0;
size = 0;
misses = 0;
ArduControl::MonitorTask::MonitorTask():
+ Task("Monitor"),
voltage(0),
current(0),
base_level(0),
bool ArduControl::MonitorTask::get_work(PendingCommand &cmd)
{
- Time::TimeStamp t = Time::now();
- if(t<next_poll)
- return false;
-
if(next_type==0)
cmd.command[0] = READ_INPUT_VOLTAGE;
else
cmd.command[0] = READ_TRACK_CURRENT;
cmd.length = 1;
- next_poll = t+200*Time::msec;
+ sleep(200*Time::msec);
next_type = (next_type+1)%5;
return true;
bool ArduControl::ControlThread::get_work(PendingCommand &cmd)
{
- for(vector<Task *>::iterator i=tasks.begin(); i!=tasks.end(); ++i)
- if((*i)->get_work(cmd))
+ Time::TimeStamp t = Time::now();
+
+ unsigned count = 0;
+ for(; (count<tasks.size() && tasks[count]->get_sleep_timeout()<=t); ++count) ;
+
+ for(; count>0; --count)
+ {
+ unsigned i = 0;
+ for(unsigned j=1; j<count; ++j)
+ if(tasks[j]->get_priority()<tasks[i]->get_priority())
+ i = j;
+
+ Task *task = tasks[i];
+ bool result = task->get_work(cmd);
+
+ Time::TimeStamp st = max(task->get_sleep_timeout(), t);
+ for(; (i+1<tasks.size() && tasks[i+1]->get_sleep_timeout()<=st); ++i)
+ tasks[i] = tasks[i+1];
+ tasks[i] = task;
+
+ if(result)
+ {
+ if(control.debug>=2)
+ IO::print("Scheduled task %s\n", task->get_name());
return true;
+ }
+ }
// As fallback, send an idle packet for the MM protocol
cmd.command[0] = MOTOROLA_SPEED;
class Task
{
protected:
- Task() { }
+ std::string name;
+ unsigned priority;
+ Msp::Time::TimeStamp sleep_timeout;
+
+ Task(const std::string &, unsigned = 0);
public:
virtual ~Task() { }
+ const std::string &get_name() const { return name; }
+
virtual bool get_work(PendingCommand &) = 0;
virtual void process_reply(const char *, unsigned) { }
+
+ unsigned get_priority() const { return priority; }
+ const Msp::Time::TimeStamp &get_sleep_timeout() const { return sleep_timeout; }
+ protected:
+ void sleep(const Msp::Time::TimeDelta &);
};
class CommandQueueTask: public Task
Queue<PendingCommand> queue;
public:
+ CommandQueueTask();
+
virtual bool get_work(PendingCommand &);
void push(const PendingCommand &);
ArduControl &control;
unsigned n_octets;
unsigned octets_remaining;
- unsigned delay;
public:
S88Task(ArduControl &);
{
private:
unsigned serial;
- Msp::Time::TimeStamp next;
public:
MfxAnnounceTask();
private:
ArduControl &control;
unsigned next_address;
- Msp::Time::TimeStamp next;
unsigned size;
unsigned bits;
unsigned misses;
float current;
float base_level;
float peak_level;
- Msp::Time::TimeStamp next_poll;
unsigned next_type;
public: