Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members  

sgnlman.cpp

Go to the documentation of this file.
00001 // $Id$
00002 
00003 //**********************************************************************
00004 //                                                                     *
00005 //    Description:   'Bell Master' Signalman class.                    *
00006 //                                                                     *
00007 //    Author:        Chris White (whitecf@bcs.org.uk)                  *
00008 //                                                                     *
00009 //    Copyright (C) 2003  Monitor Computing Services Ltd.              *
00010 //                                                                     *
00011 //    This program is free software; you can redistribute it and/or    *
00012 //    modify it under the terms of the GNU General Public License      *
00013 //    as published by the Free Software Foundation; either version 2   *
00014 //    of the License, or any later version.                            *
00015 //                                                                     *
00016 //    This program is distributed in the hope that it will be useful,  *
00017 //    but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00018 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00019 //    GNU General Public License for more details.                     *
00020 //                                                                     *
00021 //    You should have received a copy of the GNU General Public        *
00022 //    License (http://www.gnu.org/copyleft/gpl.html) along with this   *
00023 //    program; if not, write to:                                       *
00024 //       The Free Software Foundation Inc.,                            *
00025 //       59 Temple Place - Suite 330,                                  *
00026 //       Boston, MA  02111-1307,                                       *
00027 //       USA.                                                          *
00028 //                                                                     *
00029 //**********************************************************************
00030 //                                                                     *
00031 //    Notes:                                                           *
00032 //                                                                     *
00033 //**********************************************************************
00034 
00035 #include <mem.h>
00036 
00037 #include <bell.h>
00038 #include <callback.h>
00039 #include <mytrace.h>
00040 #include "tapper.h"
00041 #include <timeout.h>
00042 #include <timer.h>
00043 
00044 #include "sgnlman.h"
00045 
00046 
00047 
00048 using namespace Monitor::BellMaster;
00049 namespace Ut = Monitor::Utility;
00050 
00051 
00052 
00053 Signalman::Signalman(const string&     newName,
00054                      const unsigned    newBeatInterval,
00055                      const unsigned    newSetInterval) :
00056     name(newName), beatInterval(newBeatInterval), setInterval(newSetInterval),
00057     ringTimer(0), ringTimeout(0)
00058 {
00059     _USEMYTRACE_("Signalman::Signalman"
00060                  "(newName, newBeatInterval, newSetInterval)")
00061 }
00062 
00063 
00064 
00065 Signalman::~Signalman()
00066 {
00067     _USEMYTRACE_("Signalman::~Signalman()")
00068 
00069 
00070     // Destruction shouldn't happen whilst listening to a bell but just in case
00071     // make sure things are tidied up.
00072     delete ringTimer, ringTimer = 0;
00073     delete ringTimeout, ringTimeout = 0;
00074 }
00075 
00076 
00077 
00078 Signalman&
00079 Signalman::operator=(const Signalman&    other)
00080 {
00081     name         = other.name;
00082     beatInterval = other.beatInterval;
00083     setInterval  = other.setInterval;
00084 
00085     return *this;
00086 }
00087 
00088 
00089 
00090 int
00091 Signalman::operator==(const Signalman&    other) const
00092 {
00093     return ((name         == other.name) &&
00094             (beatInterval == other.beatInterval) &&
00095             (setInterval  == other.setInterval));
00096 }
00097 
00098 
00099 
00100 int
00101 Signalman::operator<(const Signalman&    other) const
00102 {
00103     return name < other.name;
00104 }
00105 
00106 
00107 
00108 void
00109 Signalman::beatSequence(Tapper&    tapper, const string&    sequence) const
00110 {
00111     _USEMYTRACE_("Signalman::beatSequence(tapper, sequence[])")
00112 
00113 
00114     // Count the total number of beats in the sequence
00115     const unsigned char*
00116         currentSet = (const unsigned char*)sequence.c_str();
00117     unsigned
00118         numberOfBeats = 0;
00119 
00120 
00121     while (0 < *currentSet)
00122     {
00123         numberOfBeats += *currentSet;
00124         ++currentSet;
00125     }
00126 
00127     // Create a nul terminated array of beat interval times
00128     unsigned    *beatIntervals   = new unsigned[numberOfBeats + 1];
00129     unsigned    *currentInterval = beatIntervals;
00130 
00131     currentSet = (const unsigned char*)sequence.c_str();
00132 
00133     while (0 < *currentSet)
00134     {
00135         char    currentBeats = *currentSet;
00136 
00137         while (1 < currentBeats)
00138         {
00139             // Time till next beat = beat interval
00140             *currentInterval = beatInterval;
00141 
00142             ++currentInterval;
00143             --currentBeats;
00144         }
00145 
00146         // End of a set of beats, time till next beat = set interval
00147         *currentInterval = setInterval;
00148 
00149         ++currentInterval;
00150         ++currentSet;
00151     }
00152 
00153     // End of sequence, replace last time till next beat with terminating nul
00154     --currentInterval;
00155     *currentInterval = 0;
00156 
00157     tapper.beat(beatIntervals);
00158 }
00159 
00160 
00161 
00162 unsigned
00163 Signalman::getBeatInterval() const
00164 {
00165     _USEMYTRACE_("Signalman::getBeatInterval()")
00166 
00167 
00168     return beatInterval;
00169 }
00170 
00171 
00172 
00173 void
00174 Signalman::setBeatInterval(const unsigned    newInterval)
00175 {
00176     _USEMYTRACE_("Signalman::setBeatInterval(newInterval)")
00177 
00178 
00179     beatInterval = newInterval;
00180 }
00181 
00182 
00183 
00184 unsigned
00185 Signalman::getSetInterval() const
00186 {
00187     _USEMYTRACE_("Signalman::getSetInterval")
00188 
00189 
00190     return setInterval;
00191 }
00192 
00193 
00194 
00195 void
00196 Signalman::setSetInterval(const unsigned    newInterval)
00197 {
00198     _USEMYTRACE_("Signalman::setSetInterval(newInterval)()")
00199 
00200 
00201     setInterval = newInterval;
00202 }
00203 
00204 
00205 
00206 int
00207 Signalman::isBusy()
00208 {
00209     _USEMYTRACE_("Signalman::isBusy")
00210 
00211 
00212     return ((0 != ringTimer) || (0 != ringTimeout));
00213 }
00214 
00215 
00216 
00217 void
00218 Signalman::listenToBell(Bell&                      newBell,
00219                         const Ut::CallbackBase&    timeoutCallback)
00220 {
00221     _USEMYTRACE_("Signalman::listenToBell(newBell, timeoutCallback)")
00222 
00223 
00224     if (!isBusy())
00225     {
00226         ringTimer = new Ut::Timer();
00227 
00228         ringTimeout = new Ut::Timeout(timeoutCallback,
00229                                       1500,
00230                                       "ring timeout");
00231 
00232         newBell.addListener(Ut::Callback< Signalman >(*this,
00233                                                       &Signalman::hearBell));
00234 
00235 
00236         for (int index = 0; 64 > index; ++index)
00237         {
00238             heardIntervals[index] = 0;
00239         }
00240     }
00241 }
00242 
00243 
00244 
00245 void
00246 Signalman::hearBell()
00247 {
00248     _USEMYTRACE_("Signalman::hearBell()")
00249 
00250 
00251     if ((0 != ringTimer) && (0 != ringTimeout))
00252     {
00253         ringTimeout->reset(1500);
00254 
00255         for (int index = 0; 64 > index; ++index)
00256         {
00257             if (0 == heardIntervals[index])
00258             {
00259                 heardIntervals[index]     = ringTimer->restart();
00260                 heardIntervals[index + 1] = 0;
00261                 break;
00262             }
00263         }
00264     }
00265 }
00266 
00267 
00268 
00269 const string
00270 Signalman::stopListeningToBell()
00271 {
00272     _USEMYTRACE_("Signalman::stopListeningToBell()")
00273 
00274 
00275     string    heardSequence('\0');
00276 
00277 
00278     ringTimeout = 0;
00279 
00280     // Check the signalman is listening to a bell, there will be a ring timer
00281     if (0 != ringTimer)
00282     {
00283         // Destroy the ring interval timer
00284         delete ringTimer, ringTimer = 0;
00285 
00286 
00287         // Count the number of intervals
00288         int    index = 0;
00289         while (0 < heardIntervals[index])
00290         {
00291             ++index;
00292         }
00293 
00294         // Size the storage for the sequence of rings
00295         heardSequence.resize(index + 2);
00296 
00297         // Must have heard at least one ring to have got this far
00298         heardSequence[0] = 1;
00299         heardSequence[1] = 0;
00300 
00301 
00302         // Check if there was more than one ring
00303         if (0 < heardIntervals[0])
00304         {
00305             // First determine the longest interval in the sequence
00306             unsigned    maxInterval = 0;
00307 
00308             index = 0;
00309             while (0 < heardIntervals[index])
00310             {
00311                 if (maxInterval < heardIntervals[index])
00312                 {
00313                     maxInterval = heardIntervals[index];
00314                 }
00315 
00316                 ++index;
00317             }
00318 
00319             // Then determine the shortest interval in the sequence
00320             unsigned    minInterval = maxInterval;
00321 
00322             index = 0;
00323             while (0 < heardIntervals[index])
00324             {
00325                 if (minInterval > heardIntervals[index])
00326                 {
00327                     minInterval = heardIntervals[index];
00328                 }
00329 
00330                 ++index;
00331             }
00332 
00333             // Test if the shortest interval is less than 50% the longest
00334             if (!(minInterval < (maxInterval >> 1)))
00335             {
00336                 // It isn't, assume all rings with no pauses
00337                 heardSequence[0] += index;
00338             }
00339             else
00340             {
00341                 // Set the ring / pause threshold to be half the longest
00342                 // interval
00343                 unsigned    ringThreshold = maxInterval >> 1;
00344 
00345                 // Then count the rings grouped into sets of rings
00346                 int    ring = 0;
00347 
00348                 index = 0;
00349                 while (0 < heardIntervals[index])
00350                 {
00351                     if (ringThreshold < heardIntervals[index])
00352                     {
00353                         // Heard a pause, move to next set of rings
00354                         ++ring;
00355                         heardSequence[ring] = 0;
00356                     }
00357 
00358                     // Heard a ring, increment rings count for set
00359                     ++heardSequence[ring];
00360 
00361                     ++index;
00362                 }
00363                 
00364                 // Ensure there's a terminating 0 rings
00365                 heardSequence[ring + 1] = 0;
00366             }
00367         }
00368     }
00369 
00370     return heardSequence;
00371 }
00372 

Generated on Wed Oct 29 20:54:52 2003 for Bellmaster BC Common by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002