00000
00001
00002
00003
00004
00005
00006
00007 #include <alarm.h>
00008 #include <display.h>
00009
00010
00011 __BEGIN_SYS
00012
00013
00014 Timer Alarm::_timer;
00015 volatile Timer::Tick Alarm::_elapsed;
00016 Alarm::Handler Alarm::_master;
00017 Timer::Tick Alarm::_masterTicks = 1;
00018 Alarm::AlarmQueue Alarm::_requests;
00019 Alarm::HandlerQueue Alarm::_handlerQueue;
00020 Thread *Alarm::_alarmThread;
00021
00022
00023
00024 int Alarm::alarmLoop() {
00025 _alarmThread = Thread::running();
00026
00027 while (true) {
00028 Handler h = NULL;
00029
00030 DISABLE_SCHED {
00031 if (!_handlerQueue.empty()) {
00032 h = *_handlerQueue.remove()->object();
00033 }
00034 else {
00035 _alarmThread->suspend();
00036 continue;
00037 }
00038 }
00039 if (h) h();
00040 }
00041
00042 return 0;
00043 }
00044
00045 Alarm::~Alarm() {
00046 db<Alarm>(TRC) << "~Alarm()\n";
00047 _requests.remove(this);
00048 }
00049
00050 Alarm::Alarm(const RTC::Microseconds & time, int times,
00051 Handler handler) : _times(times), _link(this),
00052 _sem(0), _handler(handler), _handlerLink(&_handler) {
00053
00054 _ticks = (time + period() / 2) / period();
00055 if (_ticks && _times) {
00056 _requests.insert(&_link);
00057 }
00058 }
00059
00060 Alarm::Alarm(const RTC::Microseconds& time, int times)
00061 : _times(times), _link(this), _sem(0),
00062 _handler(NULL), _handlerLink(&_handler) {
00063
00064 _ticks = (time + period() / 2) / period();
00065 db<Alarm>(TRC) << "Alarm t=" << time
00066 << ",x=" << times << ",ticks=" << _ticks << endl;
00067 if (_ticks && times) {
00068 _requests.insert(&_link);
00069 }
00070 db<Alarm>(TRC) << "Alarm r=" << _link.rank() << " " << _ticks << endl;
00071 }
00072
00073
00074 void Alarm::master(const RTC::Microseconds& time, const Handler& handler) {
00075 db<Alarm>(TRC) << "master(t=" << time << ",h="
00076 << (void *)handler << ")\n";
00077
00078 _master = handler;
00079 _masterTicks = (time + period() / 2) / period();
00080 }
00081
00082 void Alarm::wait() {
00083 if (_times)
00084 _sem.p();
00085 }
00086
00087 void Alarm::delay(const RTC::Microseconds& time) {
00088 db<Alarm>(TRC) << "delay(t=" << time << ")\n";
00089 Alarm alarm(time, SINGLE_TIME);
00090 alarm.wait();
00091 db<Alarm>(TRC) << "exiting from delay" << endl;
00092 }
00093
00094 void Alarm::timerHandler(void) {
00095 static Timer::Tick next = 1;
00096 static Semaphore* sem = 0;
00097
00098 ++_elapsed;
00099
00100 if (Traits<Alarm>::visible) {
00101 Display display;
00102 int lin, col;
00103 display.position(&lin, &col);
00104 display.position(0, 79);
00105 display.putc(_elapsed);
00106 display.position(lin, col);
00107 }
00108
00109 if (!(_elapsed % _masterTicks))
00110 _master();
00111
00112
00113 if (next)
00114 --next;
00115 else if (!_requests.empty()) {
00116 if (sem) sem->freeResources();
00117
00118 AlarmQueue::Element* e = _requests.remove();
00119 Alarm* alarm = e->object();
00120 next = alarm->_ticks;
00121 alarm->_times--;
00122 if (alarm->_times) {
00123 _requests.insert(e);
00124 }
00125 sem = &alarm->_sem;
00126
00127 if (alarm->_handlerLink.object()) {
00128 _handlerQueue.insert(&alarm->_handlerLink);
00129 _alarmThread->resume();
00130 }
00131 }
00132 }
00133
00134 __END_SYS