kasturi rangan raghavan / Mbed 2 deprecated QRS_cpp

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
kasturir
Date:
Mon Sep 27 22:51:19 2010 +0000
Commit message:

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
qrsdet/qrsdet2-inl.h Show annotated file Show diff for this revision Revisions of this file
qrsdet/qrsfilt-inl.h Show annotated file Show diff for this revision Revisions of this file
scmRTOS/Common/OS_Kernel.cpp Show annotated file Show diff for this revision Revisions of this file
scmRTOS/Common/OS_Kernel.h Show annotated file Show diff for this revision Revisions of this file
scmRTOS/Common/OS_Services.cpp Show annotated file Show diff for this revision Revisions of this file
scmRTOS/Common/OS_Services.h Show annotated file Show diff for this revision Revisions of this file
scmRTOS/Common/scmRTOS.h Show annotated file Show diff for this revision Revisions of this file
scmRTOS/Common/scmRTOS_defs.h Show annotated file Show diff for this revision Revisions of this file
scmRTOS/Common/usrlib.cpp Show annotated file Show diff for this revision Revisions of this file
scmRTOS/Common/usrlib.h Show annotated file Show diff for this revision Revisions of this file
scmRTOS/CortexM3/OS_Target.h Show annotated file Show diff for this revision Revisions of this file
scmRTOS/CortexM3/OS_Target_asm.s Show annotated file Show diff for this revision Revisions of this file
scmRTOS/CortexM3/OS_Target_cpp.cpp Show annotated file Show diff for this revision Revisions of this file
scmRTOS/CortexM3/commdefs.h Show annotated file Show diff for this revision Revisions of this file
scmRTOS/CortexM3/device.h Show annotated file Show diff for this revision Revisions of this file
scmRTOS/scmRTOS_TARGET_CFG.h Show annotated file Show diff for this revision Revisions of this file
scmRTOS_config.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,58 @@
+// Author: kasturir@ucla.edu (Kasturi Rangan Raghavan)
+// \file
+// QRSDet library ported to OOP
+// Allows easy adjustment of sampling rates
+
+#include <mbed.h>
+#include <scmRTOS.h>
+#include <qrsdet/qrsdet2-inl.h>
+
+AnalogIn ecg_in(p20);
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+PwmOut led3(LED3);
+DigitalOut led4(LED4);
+
+
+typedef OS::process<OS::pr0, 200> TEcgSampler;
+
+TEcgSampler EcgSampler;
+
+OS::TEventFlag ecg_sampler_ef;
+
+int main() {
+    OS::Run();
+}
+
+template<> OS_PROCESS void TEcgSampler::Exec() {
+  float float_val;
+  int int_val;
+  qrsdet::QRSFilterParams qrs_filter_params(8.0);
+  qrsdet::QRSDet2 *qrs_filter =
+    new qrsdet::QRSDet2(qrs_filter_params);
+  qrsdet::DelayFilter *delay_filter = new qrsdet::DelayFilter(45);
+  for(;;) {
+    ecg_sampler_ef.Wait();
+    led2 = !led2;
+    float_val = ecg_in.read();
+    int_val = float_val * 128;
+    int qrs_val = qrs_filter->Process(int_val);
+    int delay_val = delay_filter->Process(int_val);
+    led3 = delay_val/128.0;
+    if (qrs_val > 0) led4 = !led4;
+    
+  }
+}
+
+void OS::SystemTimerUserHook() {
+    static int cnt=0;
+    if (++cnt == 8) {
+        cnt = 0;
+        led1 = !led1;
+        ecg_sampler_ef.Signal();
+    }
+}
+
+void OS::IdleProcessUserHook() {
+    __WFI();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qrsdet/qrsdet2-inl.h	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,320 @@
+#ifndef ECG_THIRD_EPLIMITED_QRSDET2_INL_H_
+#define ECG_THIRD_EPLIMITED_QRSDET2_INL_H_
+// Modified to OOP class sturcture
+// Author: Kasturi Rangan Raghavan
+/*****************************************************************************
+FILE:  qrsdet2.cpp
+AUTHOR:    Patrick S. Hamilton
+REVISED:    7/08/2002
+  ___________________________________________________________________________
+
+qrsdet2.cpp: A QRS detector.
+Copywrite (C) 2002 Patrick S. Hamilton
+
+This file is free software; you can redistribute it and/or modify it under
+the terms of the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your option) any
+later version.
+
+This software is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE.  See the GNU Library General Public License for more
+details.
+
+You should have received a copy of the GNU Library General Public License along
+with this library; if not, write to the Free Software Foundation, Inc., 59
+Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+You may contact the author by e-mail (pat@eplimited.edu) or postal mail
+(Patrick Hamilton, E.P. Limited, 35 Medford St., Suite 204 Somerville,
+MA 02143 USA).  For updates to this software, please visit our website
+(http://www.eplimited.com).
+  __________________________________________________________________________
+
+This file contains functions for detecting QRS complexes in an ECG.  The
+QRS detector requires filter functions in qrsfilt.cpp and parameter
+definitions in qrsdet.h.  QRSDet is the only function that needs to be
+visable outside of these files.
+
+Syntax:
+    int QRSDet(int ecgSample, int init) ;
+
+Description:
+    QRSDet() implements a modified version of the QRS detection
+    algorithm described in:
+
+    Hamilton, Tompkins, W. J., "Quantitative investigation of QRS
+    detection rules using the MIT/BIH arrhythmia database",
+    IEEE Trans. Biomed. Eng., BME-33, pp. 1158-1165, 1987.
+
+    Consecutive ECG samples are passed to QRSDet.  QRSDet was
+    designed for a 200 Hz sample rate.  QRSDet contains a number
+    of static variables that it uses to adapt to different ECG
+    signals.  These variables can be reset by passing any value
+    not equal to 0 in init.
+
+    Note: QRSDet() requires filters in QRSFilt.cpp
+
+Returns:
+    When a QRS complex is detected QRSDet returns the detection delay.
+
+****************************************************************/
+
+/* For memmove. */
+#ifdef __STDC__
+#include <string.h>
+#else
+#include <mem.h>
+#endif
+
+#include "qrsfilt-inl.h"
+
+
+namespace qrsdet {
+
+int mean(int *array, int datnum);
+
+int detection_thresh(int qmean, int nmean);
+
+
+// TODO(krr) : Where to put this?
+const int MEMMOVELEN = 7*sizeof(int);
+
+
+class QRSDet2 {
+ public:
+  QRSDet2(const QRSFilterParams& params)
+    : qrs_filter(params),
+      peak_detector(params),
+      first_derivative_filter(params.get_d_length()),
+      bls_check_buffer(params) {
+    rsetCount = 0;
+    sbcount = params.get_ms(1500);
+    ms_preblank_ = params.get_ms(200);
+    ms_360_ = params.get_ms(360);
+    ms_1000_ = params.get_ms(1000);
+    ms_1650_ = params.get_ms(1650);
+    ms_window_length_ = params.get_window_length();
+    ms_filter_delay_ = params.get_filter_delay();
+
+    for (int i = 0; i < 8; i++) {
+            noise[i] = 0;    /* Initialize noise buffer */
+            rrbuf[i] = ms_1000_;/* and R-to-R interval buffer. */
+    }
+        qpkcnt = maxder = lastmax = count = sbpeak = 0 ;
+        initBlank = initMax = preBlankCnt = 0 ;
+  }
+
+  int Process(int datum) {
+      int fdatum, QrsDelay = 0;
+      int newPeak, aPeak;
+      fdatum = qrs_filter.Process(datum);
+      /* Wait until normal detector is ready before calling early detections. */
+      aPeak = peak_detector.Process(fdatum);
+      if (aPeak < QRSDet2::MIN_PEAK_AMP)
+          aPeak = 0;
+
+      // Hold any peak that is detected for 200 ms
+      // in case a bigger one comes along. There
+      // can only be one QRS complex in any 200 ms window.
+
+      newPeak = 0;
+      if (aPeak && !preBlankCnt) {
+      // If there has been no peak for 200 ms
+      // save this one and start counting.
+          tempPeak = aPeak;
+          preBlankCnt = ms_preblank_;
+        } else if (!aPeak && preBlankCnt) {          
+      // If we have held onto a peak for
+      // 200 ms pass it on for evaluation.
+          if (--preBlankCnt == 0)
+              newPeak = tempPeak ;
+        } else if (aPeak) {
+      // If we were holding a peak, but
+      // this ones bigger, save it and
+          if (aPeak > tempPeak) {
+        // start counting to 200 ms again.
+              tempPeak = aPeak ;
+        preBlankCnt = ms_preblank_;
+      } else if (--preBlankCnt == 0) {
+              newPeak = tempPeak ;
+      }
+        }
+
+      // Save derivative of raw signal for T-wave and baseline
+      //   shift discrimination.
+      int deriv_datum = first_derivative_filter.Process(datum);
+    bls_check_buffer.Process(deriv_datum);
+
+      // Initialize the qrs peak buffer with the first eight
+      // local maximum peaks detected.
+      if (qpkcnt < 8) {
+          ++count;
+          if (newPeak > 0)
+        count = ms_window_length_;
+          if (++initBlank == ms_1000_) {
+              initBlank = 0;
+              qrsbuf[qpkcnt] = initMax;
+              initMax = 0;
+              ++qpkcnt;
+              if (qpkcnt == 8) {
+                  qmean = mean(qrsbuf, 8) ;
+                  nmean = 0 ;
+                  rrmean = ms_1000_ ;
+                  sbcount = ms_1650_ ;
+                  det_thresh = detection_thresh(qmean,nmean) ;
+                  }
+              }
+          if (newPeak > initMax)
+              initMax = newPeak ;
+          }
+
+      else    /* Else test for a qrs. */
+          {
+          ++count ;
+          if(newPeak > 0)
+              {
+            
+            
+              /* Check for maximum derivative and matching minima and maxima
+                 for T-wave and baseline shift rejection.  Only consider this
+                 peak if it doesn't seem to be a base line shift. */
+                 
+              if(!bls_check_buffer.BLSCheck(&maxder))
+                  {
+
+
+                  // Classify the beat as a QRS complex
+                  // if the peak is larger than the detection threshold.
+
+                  if(newPeak > det_thresh)
+                      {
+                      memmove(&qrsbuf[1], qrsbuf, MEMMOVELEN) ;
+                      qrsbuf[0] = newPeak ;
+                      qmean = mean(qrsbuf,8) ;
+                      det_thresh = detection_thresh(qmean,nmean) ;
+                      memmove(&rrbuf[1], rrbuf, MEMMOVELEN) ;
+                      rrbuf[0] = count - ms_window_length_ ;
+                      rrmean = mean(rrbuf,8) ;
+                      sbcount = rrmean + (rrmean >> 1) + ms_window_length_ ;
+                      count = ms_window_length_ ;
+
+                      sbpeak = 0 ;
+
+                      lastmax = maxder ;
+                      maxder = 0 ;
+                      QrsDelay =  ms_window_length_ + ms_filter_delay_ ;
+                      initBlank = initMax = rsetCount = 0 ;
+                      }
+
+                  // If a peak isn't a QRS update noise buffer and estimate.
+                  // Store the peak for possible search back.
+
+
+                  else
+                      {
+                      memmove(&noise[1],noise,MEMMOVELEN) ;
+                      noise[0] = newPeak ;
+                      nmean = mean(noise,8) ;
+                      det_thresh = detection_thresh(qmean,nmean) ;
+
+                      // Don't include early peaks (which might be T-waves)
+                      // in the search back process.  A T-wave can mask
+                      // a small following QRS.
+
+                      if((newPeak > sbpeak) && ((count-ms_window_length_) >= ms_360_))
+                          {
+                          sbpeak = newPeak ;
+                          sbloc = count  - ms_window_length_ ;
+                          }
+                      }
+                  }
+              }
+        
+          /* Test for search back condition.  If a QRS is found in  */
+          /* search back update the QRS buffer and det_thresh.      */
+
+          if((count > sbcount) && (sbpeak > (det_thresh >> 1)))
+              {
+              memmove(&qrsbuf[1],qrsbuf,MEMMOVELEN) ;
+              qrsbuf[0] = sbpeak ;
+              qmean = mean(qrsbuf,8) ;
+              det_thresh = detection_thresh(qmean,nmean) ;
+              memmove(&rrbuf[1],rrbuf,MEMMOVELEN) ;
+              rrbuf[0] = sbloc ;
+              rrmean = mean(rrbuf,8) ;
+              sbcount = rrmean + (rrmean >> 1) + ms_window_length_ ;
+              QrsDelay = count = count - sbloc ;
+              QrsDelay += ms_filter_delay_;
+              sbpeak = 0 ;
+              lastmax = maxder ;
+              maxder = 0 ;
+
+              initBlank = initMax = rsetCount = 0 ;
+              }
+          }
+
+      // In the background estimate threshold to replace adaptive threshold
+      // if eight seconds elapses without a QRS detection.
+
+      if( qpkcnt == 8 )
+          {
+          if(++initBlank == ms_1000_)
+              {
+              initBlank = 0 ;
+              rsetBuff[rsetCount] = initMax ;
+              initMax = 0 ;
+              ++rsetCount ;
+
+              // Reset threshold if it has been 8 seconds without
+              // a detection.
+
+              if(rsetCount == 8)
+                  {
+                  for(int i = 0; i < 8; ++i)
+                      {
+                      qrsbuf[i] = rsetBuff[i] ;
+                      noise[i] = 0 ;
+                      }
+                  qmean = mean( rsetBuff, 8 ) ;
+                  nmean = 0 ;
+                  rrmean = ms_1000_;
+                  sbcount = ms_1650_;
+                  det_thresh = detection_thresh(qmean,nmean) ;
+                  initBlank = initMax = rsetCount = 0 ;
+                  }
+              }
+          if( newPeak > initMax )
+              initMax = newPeak ;
+          }
+
+      return(QrsDelay);
+  }
+ private:
+  int det_thresh, qpkcnt;
+    int qrsbuf[8], noise[8], rrbuf[8];
+    int rsetBuff[8], rsetCount;
+    int nmean, qmean, rrmean;
+    int count, sbpeak, sbloc, sbcount;
+    int maxder, lastmax;
+    int initBlank, initMax;
+    int preBlankCnt, tempPeak;
+  QRSFilter qrs_filter;
+  PeakDetector peak_detector;
+  DerivFilter first_derivative_filter;
+  BLSCheckBuffer bls_check_buffer;
+  size_t ms_preblank_;
+  size_t ms_360_;
+  size_t ms_1000_;
+  size_t ms_1650_;
+  size_t ms_window_length_;
+  size_t ms_filter_delay_;
+
+  // Prevents detections of peaks smaller than 150 uV.
+  static const int MIN_PEAK_AMP =  7;
+};
+
+
+}  // namespace qrsdet
+
+#endif  // ECG_THIRD_EPLIMITED_QRSDET2_INL_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qrsdet/qrsfilt-inl.h	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,427 @@
+#ifndef ECG_THIRD_EPLIMITED_QRSFILT_INL_H_
+#define ECG_THIRD_EPLIMITED_QRSFILT_INL_H_
+// Modified to OOP class sturcture
+// Author: Kasturi Rangan Raghavan
+/*****************************************************************************
+FILE:  qrsfilt.cpp
+AUTHOR:    Patrick S. Hamilton
+REVISED:    5/13/2002
+  ___________________________________________________________________________
+
+qrsfilt.cpp filter functions to aid beat detecton in electrocardiograms.
+Copywrite (C) 2000 Patrick S. Hamilton
+
+This file is free software; you can redistribute it and/or modify it under
+the terms of the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your option) any
+later version.
+
+This software is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE.  See the GNU Library General Public License for more
+details.
+
+You should have received a copy of the GNU Library General Public License along
+with this library; if not, write to the Free Software Foundation, Inc., 59
+Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+You may contact the author by e-mail (pat@eplimited.edu) or postal mail
+(Patrick Hamilton, E.P. Limited, 35 Medford St., Suite 204 Somerville,
+MA 02143 USA).  For updates to this software, please visit our website
+(http://www.eplimited.com).
+  __________________________________________________________________________
+
+    This file includes QRSFilt() and associated filtering files used for QRS
+    detection.  Only QRSFilt() and deriv1() are called by the QRS detector
+    other functions can be hidden.
+    Revisions:
+        5/13: Filter implementations have been modified to allow simplified
+            modification for different sample rates.
+*******************************************************************************/
+#include <cstdlib>
+
+namespace qrsdet {
+
+/******************************************************************************
+* Syntax:
+*    int QRSFilter(int datum, int init) ;
+* Description:
+*    QRSFilter() takes samples of an ECG signal as input and returns a sample of
+*    a signal that is an estimate of the local energy in the QRS bandwidth.  In
+*    other words, the signal has a lump in it whenever a QRS complex, or QRS
+*    complex like artifact occurs.  The filters were originally designed for data
+*  sampled at 200 samples per second, but they work nearly as well at sample
+*    frequencies from 150 to 250 samples per second.
+*
+*    The filter buffers and static variables are reset if a value other than
+*    0 is passed to QRSFilter through init.
+*******************************************************************************/
+
+class RingBuffer {
+ public:
+  RingBuffer(size_t buf_size) {
+    this->buf_size = buf_size;
+    data = new int[buf_size];
+      for (ptr = 0; ptr < buf_size; ptr++)
+          data[ptr] = 0;
+    ptr = 0;
+  }
+
+  ~RingBuffer() {
+    delete[] data;
+  }
+
+  int* GetRange(int begin, int end, int* n) {
+    *n = end - begin;
+    int* mem = new int[*n];
+    for (int p = begin, i = 0; p < end; p++, i++) {
+      mem[i] = GetValue(p);
+    }
+    return mem;
+  }
+
+  void SetValue(int value, int offset = 0) {
+    int set_ptr = ptr + offset;
+    if (set_ptr < 0) 
+      set_ptr += static_cast<int>(buf_size);
+    set_ptr %= buf_size;
+    data[set_ptr] = value;
+  }
+
+  int GetValue(int offset = 0) {
+    int get_ptr = ptr + offset;
+    if (get_ptr < 0)
+      get_ptr += static_cast<int>(buf_size);
+    get_ptr %= buf_size;
+    return data[get_ptr];
+  }
+    
+  void Increment() {
+    if (++ptr == buf_size)
+      ptr = 0;
+  }
+
+ protected:
+  size_t buf_size;
+  int* data;
+  int ptr;
+};
+
+class DelayFilter : public RingBuffer {
+ public:
+  explicit DelayFilter(size_t buf_size) : RingBuffer(buf_size) {}
+  int Process(int datum) {
+    int output = GetValue();
+    SetValue(datum);
+    Increment();
+    return output;
+  }
+};
+
+/*************************************************************************
+*  lpfilt() implements the digital filter represented by the difference
+*  equation:
+*
+*     y[n] = 2*y[n-1] - y[n-2] + x[n] - 2*x[t-24 ms] + x[t-48 ms]
+*
+*    Note that the filter delay is (LPBUFFER_LGTH/2)-1
+*
+**************************************************************************/
+class LowPassFilter : public RingBuffer {
+ public:
+  LowPassFilter(size_t buf_size) : RingBuffer(buf_size) {
+    y1 = 0;
+    y2 = 0;
+  }
+
+  int Process(int datum) {
+      int length = static_cast<int>(buf_size);
+      long y0;
+      int output, halfPtr;
+      halfPtr = ptr - length / 2;
+      if (halfPtr < 0)  // to x[n-6].
+      halfPtr += length;
+      y0 = (y1 << 1) - y2 + datum - (data[halfPtr] << 1) + data[ptr];
+      y2 = y1;
+      y1 = y0;
+      output = y0 / ((length * length) / 4);
+      data[ptr] = datum;
+    Increment();
+      return output;
+  }
+
+ private:
+  long y1, y2;
+};
+
+
+/******************************************************************************
+*  hpfilt() implements the high pass filter represented by the following
+*  difference equation:
+*
+*    y[n] = y[n-1] + x[n] - x[n-128 ms]
+*    z[n] = x[n-64 ms] - y[n] ;
+*
+*  Filter delay is (buf_size-1)/2
+******************************************************************************/
+class HighPassFilter : public RingBuffer {
+ public:
+  HighPassFilter(size_t buf_size) : RingBuffer(buf_size) {
+        y = 0;
+  }
+
+  int Process(int datum) {
+      int output, halfPtr;
+      int length = static_cast<int>(buf_size);
+    y += datum - data[ptr];
+      halfPtr = ptr - (length / 2);
+      if (halfPtr < 0)
+          halfPtr += length;
+      output = data[halfPtr] - (y / length);
+      data[ptr] = datum;
+      Increment();
+      return output;
+  }
+
+ private:
+  long y;
+};
+
+
+/*****************************************************************************
+*  deriv1 and deriv2 implement derivative approximations represented by
+*  the difference equation:
+*
+*    y[n] = x[n] - x[n - 10ms]
+*
+*  Filter delay is DERIV_LENGTH/2
+*****************************************************************************/
+class DerivFilter : public RingBuffer {
+ public:
+  DerivFilter(size_t buf_size) : RingBuffer(buf_size) {}
+
+  int Process(int datum) {
+    int y;
+    y = datum - data[ptr];
+      data[ptr] = datum;
+    Increment();
+      return y;
+  }
+};
+
+
+/*****************************************************************************
+* mvwint() implements a moving window integrator.  Actually, mvwint() averages
+* the signal values over the last WINDOW_WIDTH samples.
+*****************************************************************************/
+class MovingWindowAverager : public RingBuffer {
+ public:
+  MovingWindowAverager(size_t buf_size) : RingBuffer(buf_size) {  
+    sum = 0;
+  }
+
+  int Process(int datum) {
+    int output;
+    int length = static_cast<int>(buf_size);
+      sum += datum;
+      sum -= data[ptr];
+      data[ptr] = datum;
+    Increment();
+      if((sum / length) > 32000)
+          output = 32000 ;
+      else
+          output = sum / length;
+      return output;
+  }
+ private:
+  long sum;
+};
+
+struct QRSFilterParams {
+  QRSFilterParams(double ts) {
+    this->ts = ts;
+  }
+
+  size_t get_ms(size_t t) const { return static_cast<double>(t) / ts + 0.5; }
+
+  double get_ts() const { return ts; }
+
+  size_t get_lp_length() const { return get_ms(50); }
+
+  size_t get_hp_length() const { return get_ms(125); }
+
+  size_t get_d_length() const { return get_ms(10); }
+
+  size_t get_window_length() const { return get_ms(80); }
+
+  size_t get_preblank() const { return get_ms(200); }
+
+  size_t get_filter_delay() const {
+    return get_d_length() / 2.0 +
+           get_lp_length() / 2.0 - 1.0 +
+           (get_hp_length() - 1.0) / 2.0 +
+           get_preblank();
+  }
+
+  size_t get_der_delay() const {
+    return get_filter_delay() + get_window_length() + get_ms(100);
+  }
+
+ private:
+  double ts;
+};
+
+class QRSFilter {
+ public:
+  QRSFilter(QRSFilterParams params) :
+  lp_filter(params.get_lp_length()),
+  hp_filter(params.get_hp_length()),
+  d_filter(params.get_d_length()),
+  mwa_filter(params.get_window_length()) {}
+
+  int Process(int datum) {
+    datum = lp_filter.Process(datum);
+    datum = hp_filter.Process(datum);
+    datum = d_filter.Process(datum);
+    datum = abs(datum);
+    datum = mwa_filter.Process(datum);
+    return datum;
+  }
+
+ private:
+  LowPassFilter lp_filter;
+  HighPassFilter hp_filter;
+  DerivFilter d_filter;
+  MovingWindowAverager mwa_filter;
+};
+
+/**************************************************************
+* peak() takes a datum as input and returns a peak height
+* when the signal returns to half its peak height, or 
+**************************************************************/
+class PeakDetector {
+ public:
+  PeakDetector(const QRSFilterParams& params) {
+    max = 0;
+    timeSinceMax = 0;
+    lastDatum = 0;
+    ms_95_ = params.get_ms(95);
+  }
+
+  // what is Dly used for?
+  int Process(int datum) {
+      int pk = 0;
+      if(timeSinceMax > 0)
+          ++timeSinceMax ;
+
+      if((datum > lastDatum) && (datum > max)) {
+          max = datum;
+          if(max > 2)
+              timeSinceMax = 1;
+        } else if(datum < (max >> 1)) {
+      pk = max ;
+      max = 0 ;
+      timeSinceMax = 0 ;
+          Dly = 0 ;
+        } else if(timeSinceMax > ms_95_) {
+          pk = max;
+          max = 0;
+          timeSinceMax = 0;
+          Dly = 3;
+        }
+      lastDatum = datum ;
+      return pk;
+  }
+ private:
+  size_t ms_95_;
+  int Dly;  // unused?
+  int max;
+  int timeSinceMax;
+  int lastDatum;
+};
+
+/********************************************************************
+mean returns the mean of an array of integers.  It uses a slow
+sort algorithm, but these arrays are small, so it hardly matters.
+********************************************************************/
+int mean(int *array, int n)
+    {
+    long sum = 0;
+    for(int i = 0; i < n; ++i)
+        sum += array[i];
+    sum /= n;
+    return sum;
+    }
+
+/****************************************************************************
+ thresh() calculates the detection threshold from the qrs mean and noise
+ mean estimates.
+****************************************************************************/
+int detection_thresh(int qmean, int nmean) {
+  static const float TH = .3125;
+  int thrsh, dmed;
+  float temp;
+  dmed = qmean - nmean;
+  temp = dmed;
+  temp *= TH;
+  dmed = temp;
+  thrsh = nmean + dmed;
+  return thrsh;
+}
+
+/***********************************************************************
+    BLSCheck() reviews data to see if a baseline shift has occurred.
+    This is done by looking for both positive and negative slopes of
+    roughly the same magnitude in a 220 ms window.
+***********************************************************************/
+class BLSCheckBuffer : RingBuffer {
+ public:
+  BLSCheckBuffer(const QRSFilterParams& params)
+    : RingBuffer(params.get_der_delay()) {
+    ms150_ = params.get_ms(150);
+    ms220_ = params.get_ms(220);
+  }
+
+  int Process(int datum) {
+     data[ptr] = datum;
+     Increment();
+     return datum;
+  }
+
+  int BLSCheck(int *maxder) {
+    int max = 0, min = 0;
+    int maxt, mint;
+    int saved_ptr = ptr;
+      for(int t = 0; t < ms220_; t++) {
+          
+          int x = data[ptr];
+          if(x > max) {
+              maxt = t;
+              max = x;
+          } else if(x < min) {
+              mint = t;
+              min = x;
+          }
+        Increment();
+      }
+      ptr = saved_ptr;
+      *maxder = max;
+      min = -min;
+    
+      /* Possible beat if a maximum and minimum pair are found
+          where the interval between them is less than 150 ms. */
+         
+      if((max > (min >> 3)) && (min > (max >> 3)) &&
+          (abs(maxt - mint) < ms150_))
+          return 0;
+      else
+          return 1;
+  }
+ private:
+  size_t ms150_, ms220_;
+};
+
+
+}  // namespace qrsdet
+
+#endif  // ECG_THIRD_EPLIMITED_QRSFILT_INL_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/OS_Kernel.cpp	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,115 @@
+//******************************************************************************
+//*
+//*     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+//*
+//*     NICKNAME:  scmRTOS
+//*
+//*     PURPOSE:  OS Kernel Source
+//*
+//*     Version: 3.10
+//*
+//*     $Revision: 256 $
+//*     $Date:: 2010-01-22 #$
+//*
+//*     Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//*     Permission is hereby granted, free of charge, to any person 
+//*     obtaining  a copy of this software and associated documentation 
+//*     files (the "Software"), to deal in the Software without restriction, 
+//*     including without limitation the rights to use, copy, modify, merge, 
+//*     publish, distribute, sublicense, and/or sell copies of the Software, 
+//*     and to permit persons to whom the Software is furnished to do so, 
+//*     subject to the following conditions:
+//*
+//*     The above copyright notice and this permission notice shall be included 
+//*     in all copies or substantial portions of the Software.
+//*
+//*     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+//*     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+//*     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+//*     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+//*     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+//*     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 
+//*     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//*     =================================================================
+//*     See http://scmrtos.sourceforge.net for documentation, latest
+//*     information, license and contact details.
+//*     =================================================================
+//*
+//******************************************************************************
+
+#include "scmRTOS.h"
+
+using namespace OS;
+//------------------------------------------------------------------------------
+OS::TKernel OS::Kernel;
+
+//------------------------------------------------------------------------------
+#if scmRTOS_CONTEXT_SWITCH_SCHEME == 0
+void TKernel::Sched()
+{
+    byte NextPrty = GetHighPriority(ReadyProcessMap);
+    if(NextPrty != CurProcPriority)
+    {
+        TStackItem*  Next_SP = ProcessTable[NextPrty]->StackPointer;
+        TStackItem** Curr_SP_addr = &(ProcessTable[CurProcPriority]->StackPointer);
+        CurProcPriority = NextPrty;
+        OS_ContextSwitcher(Curr_SP_addr, Next_SP);
+    }
+}
+#else
+//------------------------------------------------------------------------------
+void TKernel::Sched()
+{
+    byte NextPrty = GetHighPriority(ReadyProcessMap);
+    if(NextPrty != CurProcPriority)
+    {
+        SchedProcPriority = NextPrty;
+    
+        RaiseContextSwitch();
+        do
+        {
+            EnableContextSwitch();
+            DUMMY_INSTR();
+            DisableContextSwitch();
+        } 
+        while(!IsContextSwitchDone());
+    }
+}
+//------------------------------------------------------------------------------
+TStackItem* OS_ContextSwitchHook(TStackItem* sp) { return OS::Kernel.ContextSwitchHook(sp); }
+//------------------------------------------------------------------------------
+#endif // scmRTOS_CONTEXT_SWITCH_SCHEME
+//------------------------------------------------------------------------------
+void TBaseProcess::Sleep(TTimeout timeout)
+{
+    TCritSect cs;
+
+    Kernel.ProcessTable[Kernel.CurProcPriority]->Timeout = timeout;
+    Kernel.SetProcessUnready(Kernel.CurProcPriority);
+    Kernel.Scheduler();
+}
+//------------------------------------------------------------------------------
+void OS::WakeUpProcess(TBaseProcess& p)
+{
+    TCritSect cs;
+
+    if(p.Timeout)
+    {
+        p.Timeout = 0;
+        Kernel.SetProcessReady(p.Priority);
+        Kernel.Scheduler();
+    }
+}
+//------------------------------------------------------------------------------
+void OS::ForceWakeUpProcess(TBaseProcess& p)
+{
+    TCritSect cs;
+
+    p.Timeout = 0;
+    Kernel.SetProcessReady(p.Priority);
+    Kernel.Scheduler();
+}
+//------------------------------------------------------------------------------
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/OS_Kernel.h	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,426 @@
+//******************************************************************************
+//*
+//*     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+//*
+//*     NICKNAME:  scmRTOS
+//*
+//*     PURPOSE:  OS Kernel Header. Declarations And Definitions
+//*
+//*     Version: 3.10
+//*
+//*     $Revision: 256 $
+//*     $Date:: 2010-01-22 #$
+//*
+//*     Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//*     Permission is hereby granted, free of charge, to any person
+//*     obtaining  a copy of this software and associated documentation
+//*     files (the "Software"), to deal in the Software without restriction,
+//*     including without limitation the rights to use, copy, modify, merge,
+//*     publish, distribute, sublicense, and/or sell copies of the Software,
+//*     and to permit persons to whom the Software is furnished to do so,
+//*     subject to the following conditions:
+//*
+//*     The above copyright notice and this permission notice shall be included
+//*     in all copies or substantial portions of the Software.
+//*
+//*     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//*     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//*     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//*     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//*     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//*     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//*     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//*     =================================================================
+//*     See http://scmrtos.sourceforge.net for documentation, latest
+//*     information, license and contact details.
+//*     =================================================================
+//*
+//*****************************************************************************
+
+#ifndef OS_KERNEL_H
+#define OS_KERNEL_H
+
+#include <stddef.h>
+#include <commdefs.h>
+#include <usrlib.h>
+
+//------------------------------------------------------------------------------
+
+//==============================================================================
+extern "C" void OS_Start(TStackItem* sp);
+
+#if scmRTOS_CONTEXT_SWITCH_SCHEME == 0
+    extern "C" void OS_ContextSwitcher(TStackItem** Curr_SP, TStackItem* Next_SP);
+#else
+    extern "C" TStackItem* OS_ContextSwitchHook(TStackItem* sp);
+#endif
+
+//==============================================================================
+
+//------------------------------------------------------------------------------
+//
+//
+//     NAME       :   OS
+//
+//     PURPOSE    :   Namespace for all OS stuff
+//
+//     DESCRIPTION:   Includes:  Kernel,
+//                               Processes,
+//                               Mutexes,
+//                               Event Flags,
+//                               Byte-wide Channels,
+//                               Arbitrary-type Channels,
+//                               Messages
+//
+namespace OS
+{
+    class TBaseProcess;
+
+    INLINE inline void SetPrioTag(TProcessMap& pm, const TProcessMap PrioTag) { pm |=  PrioTag; }
+    INLINE inline void ClrPrioTag(TProcessMap& pm, const TProcessMap PrioTag) { pm &= ~PrioTag; }
+
+    //--------------------------------------------------------------------------
+    //
+    //     NAME       :   TKernel
+    //
+    ///  Implements kernel-level operations such as
+    ///  process management, process-level scheduling,
+    ///  ISR-level scheduling, system timing.
+    //
+    //     DESCRIPTION:
+    //
+    //
+    class TKernel
+    {
+        //-----------------------------------------------------------
+        //
+        //     Declarations
+        //
+        
+
+        friend class TISRW;
+        friend class TISRW_SS;
+        friend class TBaseProcess;
+        friend class TMutex;
+        friend class TEventFlag;
+        friend class TChannel;
+        friend class TBaseMessage;
+
+        template<typename T, word size, class S> friend class channel;
+        template<typename T>                     friend class message;
+
+        friend void          Run();
+        friend void          WakeUpProcess(TBaseProcess& p);
+        friend void          ForceWakeUpProcess(TBaseProcess& p);
+        friend inline bool   IsProcessSleeping(const TBaseProcess& p);
+        friend inline bool   IsProcessSuspended(const TBaseProcess& p);
+        friend inline dword  GetTickCount();
+
+        //-----------------------------------------------------------
+        //
+        //      Data
+        //
+    private:
+        byte CurProcPriority;
+        TProcessMap ReadyProcessMap;
+        TBaseProcess* ProcessTable[scmRTOS_PROCESS_COUNT+1];
+        volatile byte ISR_NestCount;
+
+    #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
+        byte SchedProcPriority;
+    #endif
+
+    #if scmRTOS_SYSTEM_TICKS_ENABLE == 1
+        volatile dword SysTickCount;
+    #endif
+
+    //-----------------------------------------------------------
+    //
+    //      Functions
+    //
+    public:
+        INLINE TKernel()
+            : CurProcPriority(pr0)
+            , ReadyProcessMap( (1 << (scmRTOS_PROCESS_COUNT + 1)) - 1)  // set all processes ready
+            , ISR_NestCount(0)
+        {
+        }
+
+    private:
+        INLINE inline void RegisterProcess(TBaseProcess* const p);
+
+        void Sched();
+        INLINE void Scheduler() { if(ISR_NestCount) return; else  Sched(); }
+        INLINE inline void SchedISR();
+
+    #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
+        INLINE inline bool IsContextSwitchDone() const volatile;
+    #endif
+        INLINE void SetProcessReady  (const byte pr) { TProcessMap PrioTag = GetPrioTag(pr); SetPrioTag( ReadyProcessMap, PrioTag); }
+        INLINE void SetProcessUnready(const byte pr) { TProcessMap PrioTag = GetPrioTag(pr); ClrPrioTag( ReadyProcessMap, PrioTag); }
+
+    public:
+        INLINE inline void SystemTimer();
+    #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
+        INLINE inline TStackItem* ContextSwitchHook(TStackItem* sp);
+    #endif
+
+    };  // End of TKernel class definition
+    //--------------------------------------------------------------------------
+    extern TKernel Kernel;
+
+    //--------------------------------------------------------------------------
+    //
+    /// BaseProcess
+    ///
+    /// Implements base class-type for application processes
+    //
+    //      DESCRIPTION:
+    //
+    //
+    class TBaseProcess
+    {
+        friend class TKernel;
+        friend class TISRW;
+        friend class TISRW_SS;
+        friend class TEventFlag;
+        friend class TMutex;
+        friend class TBaseMessage;
+
+        template<typename T, word size, class S> friend class channel;
+        template<typename T>                     friend class message;
+
+
+        friend void         Run();
+        friend void         WakeUpProcess(TBaseProcess& p);
+        friend void         ForceWakeUpProcess(TBaseProcess& p);
+        friend bool         IsProcessSleeping(const TBaseProcess& p);
+        friend bool         IsProcessSuspended(const TBaseProcess& p);
+
+    public:
+    #if SEPARATE_RETURN_STACK == 0
+        TBaseProcess( TStackItem* Stack, TPriority pr, void (*exec)() );
+    #else
+        TBaseProcess( TStackItem* Stack, TStackItem* RStack, TPriority pr, void (*exec)() );
+    #endif
+
+        static void Sleep(TTimeout timeout = 0);
+
+    protected:
+        TStackItem* StackPointer;
+        TTimeout Timeout;
+        TPriority Priority;
+    };
+    //--------------------------------------------------------------------------
+
+    //--------------------------------------------------------------------------
+    //
+    ///  process
+    ///
+    ///  Implements template for application processes instantiation
+    //
+    //      DESCRIPTION:
+    //
+    //
+    #if SEPARATE_RETURN_STACK == 0
+
+        template<TPriority pr, word stack_size>
+        class process : public TBaseProcess
+        {
+        public:
+            INLINE_PROCESS_CTOR process();
+
+            OS_PROCESS static void Exec();
+
+        private:
+            TStackItem Stack[stack_size/sizeof(TStackItem)];
+        };
+
+        template<TPriority pr, word stack_size>
+        OS::process<pr, stack_size>::process() : TBaseProcess( &Stack[stack_size/sizeof(TStackItem)]
+                                                              , pr
+                                                              , reinterpret_cast<void (*)()>(Exec) )
+        {
+        }
+
+    #else
+
+        template<TPriority pr, word stack_size, word rstack_size>
+        class process : public TBaseProcess
+        {
+        public:
+            INLINE_PROCESS_CTOR process();
+
+            OS_PROCESS static void Exec();
+
+        private:
+            TStackItem Stack [stack_size/sizeof(TStackItem)];
+            TStackItem RStack[rstack_size/sizeof(TStackItem)];
+        };
+
+        template<TPriority pr, word stack_size, word rstack_size>
+        process<pr, stack_size, rstack_size>::process() : TBaseProcess( &Stack[stack_size/sizeof(TStackItem)]
+                                                                      , &RStack[rstack_size/sizeof(TStackItem)]
+                                                                      , pr
+                                                                      , reinterpret_cast<void (*)()>(Exec))
+        {
+        }
+
+    #endif
+    //--------------------------------------------------------------------------
+
+    //--------------------------------------------------------------------------
+    //
+    //       Miscellaneous
+    //
+    //
+    INLINE inline void Run();
+    INLINE inline void LockSystemTimer()   { TCritSect cs; LOCK_SYSTEM_TIMER();   }
+    INLINE inline void UnlockSystemTimer() { TCritSect cs; UNLOCK_SYSTEM_TIMER(); }
+    void WakeUpProcess(TBaseProcess& p);
+    void ForceWakeUpProcess(TBaseProcess& p);
+    INLINE inline void Sleep(TTimeout t = 0) { TBaseProcess::Sleep(t); }
+
+    INLINE inline bool IsProcessSleeping(const TBaseProcess& p)
+    {
+        TCritSect cs;
+        if(p.Timeout)
+            return true;
+        else
+            return false;
+    }
+
+    INLINE inline bool IsProcessSuspended(const TBaseProcess& p)
+    {
+        TCritSect cs;
+        if(Kernel.ReadyProcessMap & GetPrioTag(p.Priority))
+            return false;
+        else
+            return true;
+    }
+    //--------------------------------------------------------------------------
+
+#if scmRTOS_SYSTEM_TICKS_ENABLE == 1
+    INLINE inline dword GetTickCount() { TCritSect cs; return Kernel.SysTickCount; }
+#endif
+
+#if scmRTOS_SYSTIMER_HOOK_ENABLE == 1
+    INLINE_SYS_TIMER_HOOK void  SystemTimerUserHook();
+#endif
+
+#if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1
+    INLINE_CONTEXT_SWITCH_HOOK void  ContextSwitchUserHook();
+#endif
+    
+}
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//
+///  Register Process
+///
+///  Places pointer to process in kernel's process table
+//
+void OS::TKernel::RegisterProcess(OS::TBaseProcess* const p)
+{
+    ProcessTable[p->Priority] = p;
+}
+//------------------------------------------------------------------------------
+//
+/// System Timer Implementation
+///
+/// Performs process's timeouts checking and
+///               moving processes to ready-to-run state
+//
+void OS::TKernel::SystemTimer()
+{
+    SYS_TIMER_CRIT_SECT();
+#if scmRTOS_SYSTEM_TICKS_ENABLE == 1
+    SysTickCount++;
+#endif
+
+#if scmRTOS_PRIORITY_ORDER == 0
+    const byte BaseIndex = 0;
+#else
+    const byte BaseIndex = 1;
+#endif
+
+    for(byte i = BaseIndex; i < (scmRTOS_PROCESS_COUNT + BaseIndex); i++)
+    {
+        TBaseProcess* p = ProcessTable[i];
+
+        if(p->Timeout > 0)
+        {
+            if(--p->Timeout == 0)
+            {
+                SetProcessReady(p->Priority);
+            }
+        }
+    }
+}
+//------------------------------------------------------------------------------
+//
+///    ISR optimized scheduler
+///
+///    !!! IMPORTANT: This function must be call from ISR services only !!!
+//
+//
+#if scmRTOS_CONTEXT_SWITCH_SCHEME == 0
+void OS::TKernel::SchedISR()
+{
+    byte NextPrty = GetHighPriority(ReadyProcessMap);
+    if(NextPrty != CurProcPriority)
+    {
+        TStackItem*  Next_SP = ProcessTable[NextPrty]->StackPointer;
+        TStackItem** Curr_SP_addr = &(ProcessTable[CurProcPriority]->StackPointer);
+        CurProcPriority = NextPrty;
+        OS_ContextSwitcher(Curr_SP_addr, Next_SP);
+    }
+}
+#else
+void OS::TKernel::SchedISR()
+{
+    byte NextPrty = GetHighPriority(ReadyProcessMap);
+    if(NextPrty != CurProcPriority)
+    {
+        SchedProcPriority    = NextPrty;
+        RaiseContextSwitch();
+    }
+}
+//------------------------------------------------------------------------------
+bool OS::TKernel::IsContextSwitchDone() const volatile
+{
+     byte cur    = CurProcPriority;    ///< reading to temporary vars is performed due to
+     byte sched  = SchedProcPriority;  ///< suppress warning about order of volatile access
+     return cur == sched;
+}
+//------------------------------------------------------------------------------
+TStackItem* OS::TKernel::ContextSwitchHook(TStackItem* sp)
+{
+    ProcessTable[CurProcPriority]->StackPointer = sp;
+    sp = ProcessTable[SchedProcPriority]->StackPointer;
+
+#if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1
+    ContextSwitchUserHook();
+#endif 
+
+    CurProcPriority = SchedProcPriority;
+    return sp;
+}
+//------------------------------------------------------------------------------
+#endif // scmRTOS_CONTEXT_SWITCH_SCHEME
+
+//-----------------------------------------------------------------------------
+/// Start Operation
+INLINE inline void OS::Run()
+{
+    TStackItem* sp = Kernel.ProcessTable[pr0]->StackPointer;
+    OS_Start(sp);
+}
+
+#include <OS_Services.h>
+
+#endif // OS_KERNEL_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/OS_Services.cpp	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,298 @@
+//******************************************************************************
+//*
+//*     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+//*
+//*     NICKNAME:  scmRTOS
+//*
+//*     PURPOSE:  OS Services Source
+//*
+//*     Version: 3.10
+//*
+//*     $Revision: 256 $
+//*     $Date:: 2010-01-22 #$
+//*
+//*     Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//*     Permission is hereby granted, free of charge, to any person
+//*     obtaining  a copy of this software and associated documentation
+//*     files (the "Software"), to deal in the Software without restriction,
+//*     including without limitation the rights to use, copy, modify, merge,
+//*     publish, distribute, sublicense, and/or sell copies of the Software,
+//*     and to permit persons to whom the Software is furnished to do so,
+//*     subject to the following conditions:
+//*
+//*     The above copyright notice and this permission notice shall be included
+//*     in all copies or substantial portions of the Software.
+//*
+//*     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//*     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//*     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//*     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//*     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//*     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//*     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//*     =================================================================
+//*     See http://scmrtos.sourceforge.net for documentation, latest
+//*     information, license and contact details.
+//*     =================================================================
+//*
+//******************************************************************************
+
+#include "scmRTOS.h"
+
+using namespace OS;
+
+//------------------------------------------------------------------------------
+//
+//
+//      TEventFlag
+//
+//
+bool OS::TEventFlag::Wait(TTimeout timeout)
+{
+    TCritSect cs;
+
+    if(Value)                                           // if flag already signaled
+    {
+        Value = efOff;                                  // clear flag
+        return true;
+    }
+    else
+    {
+        TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
+        p->Timeout = timeout;
+        TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+
+        SetPrioTag(ProcessMap, PrioTag);                // put current process to the wait map
+        ClrPrioTag(Kernel.ReadyProcessMap, PrioTag);    // remove current process from the ready map
+
+        Kernel.Scheduler();
+
+        p->Timeout = 0;
+
+        if( !(ProcessMap & PrioTag) )                   // if waked up by signal() or signal_ISR()
+            return true;
+
+        ClrPrioTag(ProcessMap, PrioTag);                // otherwise waked up by timeout or by
+        return false;                                   // OS::ForceWakeUpProcess(), remove process from the wait map
+    }
+}
+//------------------------------------------------------------------------------
+void OS::TEventFlag::Signal()
+{
+    TCritSect cs;
+    if(ProcessMap)                                          // if any process waits for event
+    {
+        TProcessMap Timeouted = Kernel.ReadyProcessMap;     // Process has its tag set in ReadyProcessMap if timeout expired
+                                                            // or it was waked up by OS::ForceWakeUpProcess()
+
+        if( ProcessMap & ~Timeouted )                       // if any process has to be waked up
+        {
+            SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map
+            ClrPrioTag(ProcessMap, ~Timeouted);             // remove all non-timeouted processes from the waiting map.
+                                                            // Used to check that process waked up by signal() or signalISR()
+                                                            // and not by timeout or OS::ForceWakeUpProcess()
+            Kernel.Scheduler();
+            return;
+        }
+    }
+    Value = efOn;
+}
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//
+//
+//      TMutex
+//
+//
+void OS::TMutex::Lock()
+{
+    TCritSect cs;
+
+    TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+    while(ValueTag)
+    {
+        SetPrioTag(ProcessMap, PrioTag);             // mutex already locked by another process, put current process to the wait map
+        ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+
+        Kernel.Scheduler();
+    }
+    ValueTag = PrioTag;                              // mutex has been successfully locked
+}
+//------------------------------------------------------------------------------
+void OS::TMutex::Unlock()
+{
+    TCritSect cs;
+
+    TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+    if(ValueTag != PrioTag) return;                  // the only process that had locked mutex can unlock the mutex
+    ValueTag = 0;
+    if(ProcessMap)
+    {
+        byte pr = GetHighPriority(ProcessMap);
+        PrioTag = GetPrioTag(pr);
+        ClrPrioTag(ProcessMap, PrioTag);             // remove next ready process from the wait map
+        SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map
+        Kernel.Scheduler();
+    }
+}
+//------------------------------------------------------------------------------
+void OS::TMutex::UnlockISR()
+{
+    TCritSect cs;
+
+    ValueTag = 0;
+    if(ProcessMap)
+    {
+        byte pr = GetHighPriority(ProcessMap);
+        TProcessMap PrioTag = GetPrioTag(pr);
+        ClrPrioTag(ProcessMap, PrioTag);             // remove next ready process from the wait map
+        SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map
+    }
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+//
+//
+//      TChannel
+//
+//
+void OS::TChannel::CheckWaiters(TProcessMap& pm)
+{
+    if(pm)
+    {
+        byte pr = GetHighPriority(pm);
+        TProcessMap PrioTag = GetPrioTag(pr);
+        ClrPrioTag(pm, PrioTag);                     // remove next ready process from the wait map
+        SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map
+        Kernel.Scheduler();
+    }
+}
+//------------------------------------------------------------------------------
+void OS::TChannel::Push(byte x)
+{
+    TCritSect cs;
+
+    while (!Cbuf.get_free_size())
+    {
+        TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+        SetPrioTag  (ProducersProcessMap, PrioTag);  // channel is full, put current process to the wait map
+        ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+        Kernel.Scheduler();                          // wait until waked-up by Pop() or Read()
+    }
+
+    Cbuf.put(x);
+    CheckWaiters(ConsumersProcessMap);
+}
+//------------------------------------------------------------------------------
+byte OS::TChannel::Pop()
+{
+    TCritSect cs;
+    byte x;
+
+    while(!Cbuf.get_count())
+    {
+        TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+        SetPrioTag(ConsumersProcessMap, PrioTag);    // channel is empty, put current process to the wait map
+        ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+        Kernel.Scheduler();                          // wait until waked up by Push() or Write()
+    }
+    x = Cbuf.get();
+    CheckWaiters(ProducersProcessMap);
+    return x;
+}
+//------------------------------------------------------------------------------
+void OS::TChannel::Write(const byte* data, const byte count)
+{
+    TCritSect cs;
+
+    while(Cbuf.get_free_size() < count)
+    {
+        TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+        SetPrioTag(ProducersProcessMap, PrioTag);    // channel has not enough space, put current process to the wait map
+        ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+        Kernel.Scheduler();                          // wait until waked up by Read() or Pop()
+    }
+
+    Cbuf.write(data, count);
+    CheckWaiters(ConsumersProcessMap);
+}
+//------------------------------------------------------------------------------
+void OS::TChannel::Read(byte* const data, const byte count)
+{
+    TCritSect cs;
+
+    while(Cbuf.get_count() < count)
+    {
+        TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+        SetPrioTag(ConsumersProcessMap, PrioTag);    // channel doesn't contain enough data, put current process to the wait map
+        ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
+        Kernel.Scheduler();                          // wait until waked up by Write() or Push()
+    }
+
+    Cbuf.read(data, count);
+    CheckWaiters(ProducersProcessMap);
+}
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//
+//              OS::message template
+//
+//          Function-members implementation
+//
+//
+//------------------------------------------------------------------------------
+bool OS::TBaseMessage::wait(TTimeout timeout)
+{
+    TCritSect cs;
+
+    if(NonEmpty)                                                  // message alredy send
+    {
+        NonEmpty = false;
+        return true;
+    }
+    else
+    {
+        TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
+        p->Timeout = timeout;
+        TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+
+        SetPrioTag(ProcessMap, PrioTag);                          // put current process to the wait map
+        ClrPrioTag(Kernel.ReadyProcessMap, PrioTag);              // remove current process from the ready map
+        Kernel.Scheduler();                                       // wait until wake up
+
+        p->Timeout = 0;
+        if( !(ProcessMap & PrioTag) )                             // if waked up by send() or sendISR()
+            return true;
+
+        ClrPrioTag(ProcessMap, PrioTag);                          // otherwise waked up by timeout or by
+            return false;                                         // OS::ForceWakeUpProcess(), remove process from wait map
+    }
+}
+//------------------------------------------------------------------------------
+void OS::TBaseMessage::send()
+{
+    TCritSect cs;
+
+    if(ProcessMap)
+    {
+        TProcessMap Timeouted = Kernel.ReadyProcessMap;         // Process has its tag set in ReadyProcessMap if timeout expired,
+                                                                // or it was waked up by OS::ForceWakeUpProcess()
+        if( ProcessMap & ~Timeouted )                           // if any process has to be waked up
+        {
+            SetPrioTag(Kernel.ReadyProcessMap, ProcessMap);     // place all waiting processes to the ready map
+            ClrPrioTag(ProcessMap, ~Timeouted);                 // remove all non-timeouted processes from the waiting map.
+            Kernel.Scheduler();
+            return;
+        }
+    }
+
+    NonEmpty = true;
+}
+//------------------------------------------------------------------------------
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/OS_Services.h	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,467 @@
+//******************************************************************************
+//*
+//*     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+//*
+//*     NICKNAME:  scmRTOS
+//*
+//*     PURPOSE:  OS Services Header. Declarations And Definitions
+//*
+//*     Version: 3.10
+//*
+//*     $Revision: 256 $
+//*     $Date:: 2010-01-22 #$
+//*
+//*     Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//*     Permission is hereby granted, free of charge, to any person
+//*     obtaining  a copy of this software and associated documentation
+//*     files (the "Software"), to deal in the Software without restriction,
+//*     including without limitation the rights to use, copy, modify, merge,
+//*     publish, distribute, sublicense, and/or sell copies of the Software,
+//*     and to permit persons to whom the Software is furnished to do so,
+//*     subject to the following conditions:
+//*
+//*     The above copyright notice and this permission notice shall be included
+//*     in all copies or substantial portions of the Software.
+//*
+//*     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//*     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//*     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//*     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//*     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//*     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//*     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//*     =================================================================
+//*     See http://scmrtos.sourceforge.net for documentation, latest
+//*     information, license and contact details.
+//*     =================================================================
+//*
+//******************************************************************************
+
+#ifndef OS_SERVICES_H
+#define OS_SERVICES_H
+
+namespace OS
+{
+    //--------------------------------------------------------------------------
+    //
+    //       NAME       :   Mutex
+    //
+    /// Binary semaphore for support of mutual exclusion
+    //
+    //       DESCRIPTION:
+    //
+    //
+    class TMutex
+    {
+    public:
+        INLINE TMutex() : ProcessMap(0), ValueTag(0) { }
+        void Lock();
+        void Unlock();
+        void UnlockISR();
+
+        INLINE bool LockSoftly()     { TCritSect cs; if(ValueTag) return false; else Lock(); return true; }
+        INLINE bool IsLocked() const { TCritSect cs; if(ValueTag) return true; else return false; }
+
+    private:
+        TProcessMap ProcessMap;
+        TProcessMap ValueTag;
+
+    };
+    //--------------------------------------------------------------------------
+
+    //--------------------------------------------------------------------------
+    //
+    ///  Event Flag
+    ///
+    ///  Intended for processes synchronization and
+    ///  event notification one (or more) process by another
+    //
+    //       DESCRIPTION:
+    //
+    //
+    class TEventFlag
+    {
+    public:
+        enum TValue { efOn = 1, efOff= 0 };     // prefix 'ef' means: "Event Flag"
+
+    public:
+        INLINE TEventFlag(TValue init_val = efOff) : ProcessMap(0), Value(init_val) { }
+
+        bool Wait(TTimeout timeout = 0);
+        void Signal();
+        INLINE void Clear() { TCritSect cs; Value = efOff; }
+        INLINE inline void SignalISR();
+        INLINE bool IsSignaled() { TCritSect cs; if(Value == efOn) return true; else return false; }
+
+    private:
+        TProcessMap ProcessMap;
+        TValue      Value;
+    };
+    //--------------------------------------------------------------------------
+
+    //--------------------------------------------------------------------------
+    //
+    ///  TChannel
+    ///
+    ///  Byte-wide data channel for transferring "raw" data
+    //
+    //       DESCRIPTION:
+    //
+    //
+    class TChannel
+    {
+    public:
+        INLINE TChannel(byte* buf, byte size) : Cbuf(buf, size) { }
+        void Push(byte x);
+        byte Pop();
+        void Write(const byte* data, const byte count);
+        void Read(byte* const data, const byte count);
+
+        INLINE byte GetCount() const { TCritSect cs; return Cbuf.get_count(); }
+
+    private:
+        TProcessMap ProducersProcessMap;
+        TProcessMap ConsumersProcessMap;
+        usr::TCbuf Cbuf;
+
+    private:
+        void CheckWaiters(TProcessMap& pm);
+    };
+    //--------------------------------------------------------------------------
+
+
+    //--------------------------------------------------------------------------
+    //
+    //       NAME       :  channel
+    //
+    //       PURPOSE    :  Data channel for transferring data
+    //                     objects of arbitrary type
+    //
+    //       DESCRIPTION:
+    //
+    //
+    template<typename T, word Size, typename S = byte>
+    ///  channel
+    ///
+    ///  Data channel for transferring data objects of arbitrary type
+    class channel
+    {
+    public:
+        INLINE channel() : ProducersProcessMap(0)
+                         , ConsumersProcessMap(0)
+                         , pool()
+        {
+        }
+
+        //----------------------------------------------------------------
+        //
+        //    Data transfer functions
+        //
+        void write(const T* data, const S cnt);
+        bool read (T* const data, const S cnt, TTimeout timeout = 0);
+
+        void push      (const T& item);
+        void push_front(const T& item);
+
+        bool pop     (T& item, TTimeout timeout = 0);
+        bool pop_back(T& item, TTimeout timeout = 0);
+
+
+        //----------------------------------------------------------------
+        //
+        //    Service functions
+        //
+        INLINE S get_count()     const { TCritSect cs; return pool.get_count();     }
+        INLINE S get_free_size() const { TCritSect cs; return pool.get_free_size(); }
+        void flush();
+        //const T& operator[](const S index) { TCritSect cs; return pool[index]; }
+
+
+    private:
+        TProcessMap ProducersProcessMap;
+        TProcessMap ConsumersProcessMap;
+        usr::ring_buffer<T, Size, S> pool;
+
+    private:
+        void CheckWaiters(TProcessMap& pm);
+    };
+
+    //--------------------------------------------------------------------------
+
+    //--------------------------------------------------------------------------
+    //
+    /// message
+    ///
+    /// Template for messages
+    //
+    //       DESCRIPTION:
+    //
+    //
+    class TBaseMessage
+    {
+    public:
+        INLINE TBaseMessage() : ProcessMap(0), NonEmpty(false) { }
+
+        bool wait  (TTimeout timeout = 0);
+        void send();
+        INLINE inline void sendISR();
+        INLINE bool is_non_empty() const { TCritSect cs; return NonEmpty;  }
+        INLINE void reset       ()       { TCritSect cs; NonEmpty = false; }
+
+    private:
+        TProcessMap ProcessMap;
+        bool NonEmpty;
+    };
+    //--------------------------------------------------------------------------
+    template<typename T>
+    class message : public TBaseMessage
+    {
+    public:
+        INLINE message() : TBaseMessage()   { }
+        INLINE const T& operator=(const T& msg) { TCritSect cs; Msg = msg; return Msg; }
+        INLINE operator     T() const       { TCritSect cs; return Msg; }
+
+    private:
+        T Msg;
+    };
+    //--------------------------------------------------------------------------
+}
+//------------------------------------------------------------------------------
+//
+//          Function-members implementation
+//
+//------------------------------------------------------------------------------
+void OS::TEventFlag::SignalISR()
+{
+    TCritSect cs;
+    if(ProcessMap)                                          // if any process waits for event
+    {
+        TProcessMap Timeouted = Kernel.ReadyProcessMap;     // Process has its tag set in ReadyProcessMap if timeout
+                                                            // expired, or it was waked up by OS::ForceWakeUpProcess()
+        if( ProcessMap & ~Timeouted )                       // if any process has to be waked up
+        {
+            SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map
+            ClrPrioTag(ProcessMap, ~Timeouted);             // remove all non-timeouted processes from the waiting map.
+            return;
+        }
+    }
+    Value = efOn;
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void OS::channel<T, Size, S>::CheckWaiters(TProcessMap& pm)
+{
+    if(pm)
+    {
+        TProcessMap Timeouted = Kernel.ReadyProcessMap;
+
+        SetPrioTag(Kernel.ReadyProcessMap, pm);       // place all waiting processes to the ready map
+        ClrPrioTag(pm, ~Timeouted);                   // remove waiting processes from the wait map
+        Kernel.Scheduler();
+    }
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void OS::channel<T, Size, S>::push(const T& item)
+{
+    TCritSect cs;
+
+    while(!pool.get_free_size())
+    {
+        TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+        SetPrioTag(ProducersProcessMap, PrioTag);     // channel is full, put current process to the wait map
+        ClrPrioTag(Kernel.ReadyProcessMap, PrioTag);  // remove current process from the ready map
+        Kernel.Scheduler();
+    }
+
+    pool.push_back(item);
+    CheckWaiters(ConsumersProcessMap);
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void OS::channel<T, Size, S>::push_front(const T& item)
+{
+    TCritSect cs;
+
+    while(!pool.get_free_size())
+    {
+        TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+        SetPrioTag(ProducersProcessMap, PrioTag);     // channel is full, put current process to the wait map
+        ClrPrioTag(Kernel.ReadyProcessMap, PrioTag);  // remove current process from the ready map
+        Kernel.Scheduler();
+    }
+
+    pool.push_front(item);
+    CheckWaiters(ConsumersProcessMap);
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+bool OS::channel<T, Size, S>::pop(T& item, TTimeout timeout)
+{
+    TCritSect cs;
+
+    if(pool.get_count())
+    {
+        item = pool.pop();
+        CheckWaiters(ProducersProcessMap);
+        return true;
+    }
+    else
+    {
+        TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
+        p->Timeout = timeout;
+
+        TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+        for(;;)
+        {
+            SetPrioTag(ConsumersProcessMap, PrioTag);     // channel is empty, put current process to the wait map
+            ClrPrioTag(Kernel.ReadyProcessMap, PrioTag);  // remove current process from the ready map
+            Kernel.Scheduler();
+
+            if(pool.get_count())
+            {
+                p->Timeout = 0;
+                item = pool.pop();
+                CheckWaiters(ProducersProcessMap);
+                return true;
+            }
+
+            if(ConsumersProcessMap & PrioTag)             // waked up by timer when timeout expired
+            {                                             // or by OS::ForceWakeUpProcess()
+
+                p->Timeout = 0;                           // non-zero if waked up by ForceWakeUpProcess()
+                ClrPrioTag(ConsumersProcessMap, PrioTag); // remove current process from the wait map
+                return false;
+            }
+        }
+    }
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+bool OS::channel<T, Size, S>::pop_back(T& item, TTimeout timeout)
+{
+    TCritSect cs;
+
+    if(pool.get_count())
+    {
+        item = pool.pop_back();
+        CheckWaiters(ProducersProcessMap);
+        return true;
+    }
+    else
+    {
+        TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
+        p->Timeout = timeout;
+
+        TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+        for(;;)
+        {
+            SetPrioTag(ConsumersProcessMap, PrioTag);     // channel is empty, put current process to the wait map
+            ClrPrioTag(Kernel.ReadyProcessMap, PrioTag);  // remove current process from the ready map
+            Kernel.Scheduler();
+
+            if(pool.get_count())
+            {
+                p->Timeout = 0;
+                item = pool.pop_back();
+                CheckWaiters(ProducersProcessMap);
+                return true;
+            }
+
+            if(ConsumersProcessMap & PrioTag)             // waked up by timer when timeout expired
+            {                                             // or by OS::ForceWakeUpProcess()
+
+                p->Timeout = 0;                           // non-zero if waked up by ForceWakeUpProcess()
+                ClrPrioTag(ConsumersProcessMap, PrioTag); // remove current process from the wait map
+                return false;
+            }
+        }
+    }
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void OS::channel<T, Size, S>::flush()
+{
+    TCritSect cs;
+    pool.flush();
+    CheckWaiters(ProducersProcessMap);
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void OS::channel<T, Size, S>::write(const T* data, const S count)
+{
+    TCritSect cs;
+
+    while(pool.get_free_size() < count)
+    {
+        TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+        SetPrioTag(ProducersProcessMap, PrioTag);     // channel does not have enough space, put current process to the wait map
+        ClrPrioTag(Kernel.ReadyProcessMap, PrioTag);  // remove current process from the ready map
+        Kernel.Scheduler();
+    }
+
+    pool.write(data, count);
+    CheckWaiters(ConsumersProcessMap);
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+bool OS::channel<T, Size, S>::read(T* const data, const S count, TTimeout timeout)
+{
+    TCritSect cs;
+
+    TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
+    p->Timeout = timeout;
+
+    TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
+    while(pool.get_count() < count)
+    {
+        SetPrioTag(ConsumersProcessMap, PrioTag);     // channel doesn't contain enough data, put current process to the wait map
+        ClrPrioTag(Kernel.ReadyProcessMap, PrioTag);  // remove current process from the ready map
+        Kernel.Scheduler();
+
+        if(ConsumersProcessMap & PrioTag)             // waked up by timer when timeout expired
+        {                                             // or by OS::ForceWakeUpProcess()
+
+            p->Timeout = 0;                           // non-zero if waked up by ForceWakeUpProcess()
+            ClrPrioTag(ConsumersProcessMap, PrioTag); // remove current process from the wait map
+            return false;
+        }
+    }
+
+    p->Timeout = 0;
+    pool.read(data, count);
+    CheckWaiters(ProducersProcessMap);
+
+    return true;
+}
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//
+//              OS::message template
+//
+//          Function-members implementation
+//
+//
+//------------------------------------------------------------------------------
+void OS::TBaseMessage::sendISR()
+{
+    TCritSect cs;
+
+    if(ProcessMap)
+    {
+        TProcessMap Timeouted = OS::Kernel.ReadyProcessMap;     // Process has it's tag set in ReadyProcessMap if timeout
+                                                                // expired, or it was waked up by  OS::ForceWakeUpProcess()
+        if( ProcessMap & ~Timeouted )                           // if any process has to be waked up
+        {
+            SetPrioTag(Kernel.ReadyProcessMap, ProcessMap);     // place all waiting processes to the ready map
+            ClrPrioTag(ProcessMap, ~Timeouted);                 // remove all non-timeouted processes from the waiting map.
+            return;
+        }
+    }
+    NonEmpty = true;
+}
+//------------------------------------------------------------------------------
+#endif // OS_SERVICES_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/scmRTOS.h	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,58 @@
+//******************************************************************************
+//*
+//*     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+//*
+//*     NICKNAME:  scmRTOS
+//*
+//*     PURPOSE:  Main RTOS header file
+//*
+//*     Version: 3.10
+//*
+//*     $Revision: 256 $
+//*     $Date:: 2010-01-22 #$
+//*
+//*     Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//*     Permission is hereby granted, free of charge, to any person
+//*     obtaining  a copy of this software and associated documentation
+//*     files (the "Software"), to deal in the Software without restriction,
+//*     including without limitation the rights to use, copy, modify, merge,
+//*     publish, distribute, sublicense, and/or sell copies of the Software,
+//*     and to permit persons to whom the Software is furnished to do so,
+//*     subject to the following conditions:
+//*
+//*     The above copyright notice and this permission notice shall be included
+//*     in all copies or substantial portions of the Software.
+//*
+//*     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//*     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//*     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//*     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//*     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//*     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//*     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//*     =================================================================
+//*     See http://scmrtos.sourceforge.net for documentation, latest
+//*     information, license and contact details.
+//*     =================================================================
+//*
+//******************************************************************************
+
+#ifndef scmRTOS_H
+#define scmRTOS_H
+
+//-----------------------------------------------------------------------------
+//
+//    !!! The order of includes is important !!!
+//
+#include <stddef.h>
+#include <commdefs.h>
+#include <usrlib.h>
+#include <OS_Target.h>
+
+//------------------------------------------------------------------------------
+
+
+#endif // scmRTOS_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/scmRTOS_defs.h	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,374 @@
+//******************************************************************************
+//*
+//*     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+//*
+//*     NICKNAME:  scmRTOS
+//*
+//*     PURPOSE:  Macros And Common Definitions
+//*
+//*     Version: 3.10
+//*
+//*     $Revision: 256 $
+//*     $Date:: 2010-01-22 #$
+//*
+//*     Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//*     Permission is hereby granted, free of charge, to any person
+//*     obtaining  a copy of this software and associated documentation
+//*     files (the "Software"), to deal in the Software without restriction,
+//*     including without limitation the rights to use, copy, modify, merge,
+//*     publish, distribute, sublicense, and/or sell copies of the Software,
+//*     and to permit persons to whom the Software is furnished to do so,
+//*     subject to the following conditions:
+//*
+//*     The above copyright notice and this permission notice shall be included
+//*     in all copies or substantial portions of the Software.
+//*
+//*     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//*     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//*     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//*     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//*     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//*     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//*     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//*     =================================================================
+//*     See http://scmrtos.sourceforge.net for documentation, latest
+//*     information, license and contact details.
+//*     =================================================================
+//*
+//******************************************************************************
+
+#ifndef scmRTOS_DEFS_H
+#define scmRTOS_DEFS_H
+
+#include <commdefs.h>
+
+//------------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+//
+//
+///   Macro for Channel Type definition
+//
+//
+#define DefineChannel(Name, Capacity)                                            \
+class Name : public OS::TChannel                                                 \
+{                                                                                \
+public:                                                                          \
+    Name() : OS::TChannel(buf, sizeof(buf)) { }                                  \
+                                                                                 \
+private:                                                                         \
+    byte buf[Capacity];                                                          \
+                                                                                 \
+}
+//-----------------------------------------------------------------------------
+//
+//    Check CONFIG Macro Definitions
+//
+//
+
+//----------------- scmRTOS_SYSTIMER_NEST_INTS_ENABLE -------------------------
+#ifndef scmRTOS_SYSTIMER_NEST_INTS_ENABLE
+#error "Error: Config macro scmRTOS_SYSTIMER_NEST_INTS_ENABLE must be defined!"
+#endif
+
+#if (scmRTOS_SYSTIMER_NEST_INTS_ENABLE < 0) || (scmRTOS_SYSTIMER_NEST_INTS_ENABLE > 1)
+#error "Error: scmRTOS_SYSTIMER_NEST_INTS_ENABLE must have values 0 or 1 only!"
+#endif
+
+//----------------- scmRTOS_SYSTEM_TICKS_ENABLE -------------------------------
+#ifndef scmRTOS_SYSTEM_TICKS_ENABLE
+#error "Error: Config macro scmRTOS_SYSTEM_TICKS_ENABLE must be defined!"
+#endif
+
+#if (scmRTOS_SYSTEM_TICKS_ENABLE < 0) || (scmRTOS_SYSTEM_TICKS_ENABLE > 1)
+#error "Error: scmRTOS_SYSTEM_TICKS_ENABLE must have values 0 or 1 only!"
+#endif
+
+
+//----------------- scmRTOS_SYSTIMER_HOOK_ENABLE ------------------------------
+#ifndef scmRTOS_SYSTIMER_HOOK_ENABLE
+#error "Error: Config macro scmRTOS_SYSTIMER_HOOK_ENABLE must be defined!"
+#endif
+
+#if (scmRTOS_SYSTIMER_HOOK_ENABLE < 0) || (scmRTOS_SYSTIMER_HOOK_ENABLE > 1)
+#error "Error: scmRTOS_SYSTIMER_HOOK_ENABLE must have values 0 or 1 only!"
+#endif
+
+//-------------- scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE ----------------------
+#ifndef scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE
+#error "Error: Config macro scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE must be defined!"
+#endif
+
+#if (scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE < 0) || (scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE > 1)
+#error "Error: scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE must have values 0 or 1 only!"
+#endif
+
+//----------------- scmRTOS_IDLE_HOOK_ENABLE ----------------------------------
+#ifndef scmRTOS_IDLE_HOOK_ENABLE
+#error "Error: Config macro scmRTOS_IDLE_HOOK_ENABLE must be defined!"
+#endif
+
+#if (scmRTOS_IDLE_HOOK_ENABLE < 0) || (scmRTOS_IDLE_HOOK_ENABLE > 1)
+#error "Error: scmRTOS_IDLE_HOOK_ENABLE must have values 0 or 1 only!"
+#endif
+
+//----------------- scmRTOS_CONTEXT_SWITCH_SCHEME -----------------------------
+#ifndef scmRTOS_CONTEXT_SWITCH_SCHEME
+#error "Error: Config macro scmRTOS_CONTEXT_SWITCH_SCHEME must be defined!"
+#endif
+
+#if (scmRTOS_CONTEXT_SWITCH_SCHEME < 0) || (scmRTOS_CONTEXT_SWITCH_SCHEME > 1)
+#error "Error: scmRTOS_CONTEXT_SWITCH_SCHEME must have values 0 or 1 only!"
+#endif
+
+
+//----------------- scmRTOS_PRIORITY_ORDER ------------------------------------
+#ifndef scmRTOS_PRIORITY_ORDER
+#error "Error: Config macro scmRTOS_PRIORITY_ORDER must be defined!"
+#endif
+
+#if (scmRTOS_PRIORITY_ORDER < 0) || (scmRTOS_PRIORITY_ORDER > 1)
+#error "Error: scmRTOS_PRIORITY_ORDER must have values 0 or 1 only!"
+#endif
+
+//----------------- User Hooks inlining ------------------------------------
+#ifndef INLINE_SYS_TIMER_HOOK
+#define INLINE_SYS_TIMER_HOOK
+#endif
+
+#ifndef INLINE_CONTEXT_SWITCH_HOOK
+#define INLINE_CONTEXT_SWITCH_HOOK
+#endif
+
+
+//-----------------------------------------------------------------------------
+//
+///    Priority and process map type definitions
+//
+//
+namespace OS
+{
+    #if scmRTOS_PROCESS_COUNT < 8
+        typedef byte TProcessMap;
+    #elif scmRTOS_PROCESS_COUNT < 16
+        typedef word TProcessMap;
+    #else
+        typedef dword TProcessMap;
+    #endif
+    //------------------------------------------------------
+#if scmRTOS_PRIORITY_ORDER == 0
+    enum TPriority {
+        #if scmRTOS_PROCESS_COUNT   > 0
+            pr0,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 1
+            pr1,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 2
+            pr2,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 3
+            pr3,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 4
+            pr4,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 5
+            pr5,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 6
+            pr6,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 7
+            pr7,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 8
+            pr8,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 9
+            pr9,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 10
+            pr10,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 11
+            pr11,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 12
+            pr12,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 13
+            pr13,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 14
+            pr14,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 15
+            pr15,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 16
+            pr16,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 17
+            pr17,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 18
+            pr18,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 19
+            pr19,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 20
+            pr20,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 21
+            pr21,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 22
+            pr22,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 23
+            pr23,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 24
+            pr24,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 25
+            pr25,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 26
+            pr26,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 27
+            pr27,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 28
+            pr28,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 29
+            pr29,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 30
+            pr30,
+        #endif
+        #if (scmRTOS_PROCESS_COUNT   > 31) || (scmRTOS_PROCESS_COUNT   < 1)
+            #error "Invalid Process Count specification! Must be from 1 to 31."
+        #endif
+            prIDLE
+    };
+#else   // scmRTOS_PRIORITY_ORDER == 1
+    enum TPriority {
+            prIDLE,
+        #if scmRTOS_PROCESS_COUNT   > 30
+            pr30,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 29
+            pr29,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 28
+            pr28,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 27
+            pr27,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 26
+            pr26,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 25
+            pr25,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 24
+            pr24,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 23
+            pr23,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 22
+            pr22,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 21
+            pr21,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 20
+            pr20,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 19
+            pr19,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 18
+            pr18,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 17
+            pr17,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 16
+            pr16,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 15
+            pr15,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 14
+            pr14,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 13
+            pr13,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 12
+            pr12,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 11
+            pr11,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 10
+            pr10,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 9
+            pr9,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 8
+            pr8,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 7
+            pr7,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 6
+            pr6,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 5
+            pr5,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 4
+            pr4,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 3
+            pr3,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 2
+            pr2,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 1
+            pr1,
+        #endif
+        #if scmRTOS_PROCESS_COUNT   > 0
+            pr0
+        #endif
+        #if (scmRTOS_PROCESS_COUNT   > 31) || (scmRTOS_PROCESS_COUNT   < 1)
+            #error "Invalid Process Count specification! Must be from 1 to 31."
+        #endif
+    };
+#endif //scmRTOS_PRIORITY_ORDER
+}
+//-----------------------------------------------------------------------------
+//
+//     Process's constructor inlining control: default behaviour
+//
+#ifndef INLINE_PROCESS_CTOR
+#define INLINE_PROCESS_CTOR
+#endif
+
+
+//-----------------------------------------------------------------------------
+
+#endif // scmRTOS_DEFS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/usrlib.cpp	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,140 @@
+//******************************************************************************
+//*
+//*     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+//*
+//*     NICKNAME:  scmRTOS
+//*               
+//*     PURPOSE:  User Suport Library Source
+//*               
+//*     Version: 3.10
+//*
+//*     $Revision: 256 $
+//*     $Date:: 2010-01-22 #$
+//*
+//*     Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//*     Permission is hereby granted, free of charge, to any person 
+//*     obtaining  a copy of this software and associated documentation 
+//*     files (the "Software"), to deal in the Software without restriction, 
+//*     including without limitation the rights to use, copy, modify, merge, 
+//*     publish, distribute, sublicense, and/or sell copies of the Software, 
+//*     and to permit persons to whom the Software is furnished to do so, 
+//*     subject to the following conditions:
+//*
+//*     The above copyright notice and this permission notice shall be included 
+//*     in all copies or substantial portions of the Software.
+//*
+//*     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+//*     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+//*     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+//*     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+//*     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+//*     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 
+//*     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//*     =================================================================
+//*     See http://scmrtos.sourceforge.net for documentation, latest
+//*     information, license and contact details.
+//*     =================================================================
+//*
+//******************************************************************************
+
+#include <usrlib.h>
+#include <commdefs.h>
+
+using namespace usr;
+
+//------------------------------------------------------------------------------
+//
+///   Circular buffer function-member description
+//
+//
+//
+TCbuf::TCbuf(byte* const Address, const byte Size) :
+        buf(Address),
+        size(Size),
+        count(0),
+        first(0),
+        last(0)
+{
+}
+//------------------------------------------------------------------------------
+bool TCbuf::write(const byte* data, const byte Count)
+{
+    if( Count > (size - count) )
+        return false;
+
+    for(byte i = 0; i < Count; i++)
+        push(*(data++));
+
+    return true;
+}
+//------------------------------------------------------------------------------
+void TCbuf::read(byte* data, const byte Count)
+{
+    byte N = Count <= count ? Count : count;
+
+    for(byte i = 0; i < N; i++)
+        data[i] = pop();
+}
+//------------------------------------------------------------------------------
+byte TCbuf::get_byte(const byte index) const
+{
+    byte x = first + index;
+
+    if(x < size)
+        return buf[x];
+    else
+        return buf[x - size];
+}
+
+//------------------------------------------------------------------------------
+bool TCbuf::put(const byte item)
+{
+    if(count == size)
+        return false;
+
+    push(item);
+    return true;
+}
+//------------------------------------------------------------------------------
+byte TCbuf::get()
+{
+    if(count)
+        return pop();
+    else
+        return 0;
+}
+//------------------------------------------------------------------------------
+//
+/// \note
+/// For internal purposes.
+/// Use this function with care - it doesn't perform free size check.
+//
+void TCbuf::push(const byte item)
+{
+    buf[last] = item;
+    last++;
+    count++;
+
+    if(last == size)
+        last = 0;
+}
+//------------------------------------------------------------------------------
+//
+/// \note
+/// For internal purposes.
+/// Use this function with care - it doesn't perform free size check.
+//
+byte TCbuf::pop()
+{
+    byte item = buf[first];
+
+    count--;
+    first++;
+    if(first == size)
+        first = 0;
+
+    return item;
+}
+//------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/usrlib.h	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,298 @@
+//******************************************************************************
+//*
+//*     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+//*
+//*     NICKNAME:  scmRTOS
+//*               
+//*     PURPOSE:  User Suport Library Header
+//*               
+//*     Version: 3.10
+//*
+//*     $Revision: 256 $
+//*     $Date:: 2010-01-22 #$
+//*
+//*     Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//*     Permission is hereby granted, free of charge, to any person 
+//*     obtaining  a copy of this software and associated documentation 
+//*     files (the "Software"), to deal in the Software without restriction, 
+//*     including without limitation the rights to use, copy, modify, merge, 
+//*     publish, distribute, sublicense, and/or sell copies of the Software, 
+//*     and to permit persons to whom the Software is furnished to do so, 
+//*     subject to the following conditions:
+//*
+//*     The above copyright notice and this permission notice shall be included 
+//*     in all copies or substantial portions of the Software.
+//*
+//*     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+//*     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+//*     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+//*     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+//*     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+//*     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 
+//*     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//*     =================================================================
+//*     See http://scmrtos.sourceforge.net for documentation, latest
+//*     information, license and contact details.
+//*     =================================================================
+//*
+//******************************************************************************
+
+#ifndef USRLIB_H
+#define USRLIB_H
+
+#include <commdefs.h>
+
+//------------------------------------------------------------------------------
+//
+//  DESCRIPTON: user namespace for some useful types and functions
+//
+//
+namespace usr
+{
+    //------------------------------------------------------------------------------
+    //
+    ///     The Circular Buffer
+    //
+    ///         Byte-wide FIFO.
+    //
+    ///         Allows to:
+    ///             add byte,
+    ///             get byte,
+    ///             write bytes from array,
+    ///             read bytes to array,
+    ///             and some other service actions.
+    //
+    class TCbuf
+    {
+    public:
+        TCbuf(byte* const Address, const byte Size);
+        bool write(const byte* data, const byte Count);
+        void read(byte* const data, const byte Count);
+        byte get_count() const { return count; }
+        byte get_free_size() const { return size - count; }
+        byte get_byte(const byte index) const;
+        void clear() { count = 0; last = first; }
+        bool put(const byte item);
+        byte get();
+
+    private:
+       //------------------------------------------------------------------------------
+       //
+       //  DESCRIPTON: For internal purposes
+       //
+        void push(const byte item); ///< Use this function with care - it doesn't perform free size check
+        byte pop();                 ///< Use this function with care - it doesn't perform count check
+       //------------------------------------------------------------------------------
+
+    private:
+        byte* buf;
+        byte  size;
+        volatile byte count;
+        byte  first;
+        byte  last;
+    };
+    //------------------------------------------------------------------------------
+
+
+
+    //-----------------------------------------------------------------------
+    //
+    ///     The Ring Buffer Template
+    ///
+    ///         Carries out FIFO functionality for
+    ///         arbitrary data types
+    ///
+    ///         Allows to:
+    ///             add item to back (default),
+    ///             add item to front,
+    ///             get item at front (default),
+    ///             get item from back,
+    ///             write items from array,
+    ///             read items to array and some other actions
+    //
+    //
+    //
+    template<typename T, word Size, typename S = byte>
+    class ring_buffer
+    {
+    public:
+        ring_buffer() : Count(0), First(0), Last(0) { }
+
+        //----------------------------------------------------------------
+        //
+        //    Data transfer functions
+        //
+        bool write(const T* data, const S cnt);
+        void read(T* const data, const S cnt);
+
+        bool push_back(const T item);
+        bool push_front(const T item);
+
+        T pop_front();
+        T pop_back();
+
+        bool push(const T item) { return push_back(item); }
+        T pop() { return pop_front(); }
+
+        //----------------------------------------------------------------
+        //
+        //    Service functions
+        //
+        S get_count() const { return Count; }
+        S get_free_size() const { return Size - Count; }
+        T& operator[](const S index);
+        void flush() { Count = 0; Last = First; }
+
+    private:
+        //--------------------------------------------------------------
+        //  DESCRIPTON: For internal purposes
+        //              Use this functions with care: it don't perform
+        //              free size and count check
+        //
+        void push_item(const T item);
+        void push_item_front(const T item);
+        T pop_item();
+        T pop_item_back();
+        //--------------------------------------------------------------
+
+    private:
+        S  Count;
+        S  First;
+        S  Last;
+        T  Buf[Size];
+    };
+    //------------------------------------------------------------------
+}
+//---------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+//
+//    The ring buffer function-member definitions
+//
+//
+//
+template<typename T, word Size, typename S>
+bool usr::ring_buffer<T, Size, S>::write(const T* data, const S cnt)
+{
+    if( cnt > (Size - Count) )
+        return false;
+
+    for(S i = 0; i < cnt; i++)
+        push_item(*(data++));
+
+    return true;
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void usr::ring_buffer<T, Size, S>::read(T* data, const S cnt)
+{
+    S nItems = cnt <= Count ? cnt : Count;
+
+    for(S i = 0; i < nItems; i++)
+        data[i] = pop_item();
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+T& usr::ring_buffer<T, Size, S>::operator[](const S index)
+{
+    S x = First + index;
+
+    if(x < Size)
+        return Buf[x];
+    else
+        return Buf[x - Size];
+}
+
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+bool usr::ring_buffer<T, Size, S>::push_back(const T item)
+{
+    if(Count == Size)
+        return false;
+
+    push_item(item);
+    return true;
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+bool usr::ring_buffer<T, Size, S>::push_front(const T item)
+{
+    if(Count == Size)
+        return false;
+
+    push_item_front(item);
+    return true;
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+T usr::ring_buffer<T, Size, S>::pop_front()
+{
+    if(Count)
+        return pop_item();
+    else
+        return Buf[First];
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+T usr::ring_buffer<T, Size, S>::pop_back()
+{
+    if(Count)
+        return pop_item_back();
+    else
+        return Buf[First];
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void usr::ring_buffer<T, Size, S>::push_item(const T item)
+{
+    Buf[Last] = item;
+    Last++;
+    Count++;
+
+    if(Last == Size)
+        Last = 0;
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+void usr::ring_buffer<T, Size, S>::push_item_front(const T item)
+{
+    if(First == 0)
+        First = Size - 1;
+    else
+        --First;
+    Buf[First] = item;
+    Count++;
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+T usr::ring_buffer<T, Size, S>::pop_item()
+{
+    T item = Buf[First];
+
+    Count--;
+    First++;
+    if(First == Size)
+        First = 0;
+
+    return item;
+}
+//------------------------------------------------------------------------------
+template<typename T, word Size, typename S>
+T usr::ring_buffer<T, Size, S>::pop_item_back()
+{
+
+    if(Last == 0)
+        Last = Size - 1;
+    else
+        --Last;
+
+    Count--;
+    return Buf[Last];;
+}
+//------------------------------------------------------------------------------
+
+
+#endif // USRLIB_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/CortexM3/OS_Target.h	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,236 @@
+//******************************************************************************
+//*
+//*     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+//*
+//*     NICKNAME:  scmRTOS
+//*
+//*     PROCESSOR: ARM Cortex-M3 
+//*
+//*     TOOLKIT:   RVCT (ARM)
+//*               
+//*     PURPOSE:   Target Dependent Stuff Header. Declarations And Definitions
+//*               
+//*     Version: 3.10
+//*
+//*     $Revision: 195 $
+//*     $Date:: 2008-06-19 #$
+//*
+//*     Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//*     Permission is hereby granted, free of charge, to any person 
+//*     obtaining  a copy of this software and associated documentation 
+//*     files (the "Software"), to deal in the Software without restriction, 
+//*     including without limitation the rights to use, copy, modify, merge, 
+//*     publish, distribute, sublicense, and/or sell copies of the Software, 
+//*     and to permit persons to whom the Software is furnished to do so, 
+//*     subject to the following conditions:
+//*
+//*     The above copyright notice and this permission notice shall be included 
+//*     in all copies or substantial portions of the Software.
+//*
+//*     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+//*     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+//*     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+//*     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+//*     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+//*     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 
+//*     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//*     =================================================================
+//*     See http://scmrtos.sourceforge.net for documentation, latest
+//*     information, license and contact details.
+//*     =================================================================
+//*
+//******************************************************************************
+//*     Ported by Andrey Chuikin, Copyright (c) 2008-2010
+
+#ifndef scmRTOS_CORTEXM3_H
+#define scmRTOS_CORTEXM3_H
+
+#include <commdefs.h>
+
+//------------------------------------------------------------------------------
+//
+//    Compiler and Target checks
+//
+//
+#ifndef __ARMCC_VERSION
+#error "This file should only be compiled with ARM RVCT Compiler"
+#endif // __ARMCC_VERSION
+
+#if __TARGET_ARCH_ARM != 0 || __TARGET_ARCH_THUMB != 4
+#error "This file must be compiled for ARMv7-M (Cortex-M3) processor only."
+#endif
+
+//------------------------------------------------------------------------------
+//
+//    Target specific types
+//
+//
+typedef dword TStackItem;
+typedef dword TStatusReg;
+
+//-----------------------------------------------------------------------------
+//
+//    Configuration macros
+//
+//
+#define OS_PROCESS    __attribute__((__noreturn__))
+#define OS_INTERRUPT 
+#define DUMMY_INSTR() __NOP()
+#define INLINE_PROCESS_CTOR INLINE inline
+
+//-----------------------------------------------------------------------------
+//
+//   Uncomment macro value below for SystemTimer() run in critical section
+// 
+//   This is useful (and necessary) when target processor has hardware 
+//   enabled nested interrups. Cortex-M3 have such interrupts.
+// 
+#define SYS_TIMER_CRIT_SECT()  TCritSect cs
+
+//-----------------------------------------------------------------------------
+// Separate return stack not required
+#define SEPARATE_RETURN_STACK   0
+
+//-----------------------------------------------------------------------------
+// Software interrupt stack switching not supported in Cortex-M3 port
+// because processor implements hardware stack switching.
+// So, system timer isr wrapper can't be choosen at project level
+//
+#define scmRTOS_ISRW_TYPE       TISRW
+
+//-----------------------------------------------------------------------------
+//
+//    scmRTOS Context Switch Scheme
+//
+//    The macro defines a context switch manner. Value 0 sets direct context
+//    switch in the scheduler and in the OS ISRs. This is the primary method.
+//    Value 1 sets the second way to switch context - by using of software 
+//    interrupt. See documentation fo details.
+//    Cortex-M3 port supports software interrupt switch method only.
+//
+#define  scmRTOS_CONTEXT_SWITCH_SCHEME 1
+
+//-----------------------------------------------------------------------------
+//
+//     Include project-level configurations
+//    !!! The order of includes is important !!!
+//
+#include "../../scmRTOS_config.h"
+#include "../scmRTOS_TARGET_CFG.h"
+#include <scmRTOS_defs.h>
+#include <LPC17xx.h>
+
+//-----------------------------------------------------------------------------
+//
+//     The Critital Section Wrapper
+//
+//
+#define __enable_interrupt()  __enable_irq()
+#define __disable_interrupt() __disable_irq()
+
+#define __set_interrupt_state(status) __set_PRIMASK(status)
+#define __get_interrupt_state() __get_PRIMASK()
+
+class TCritSect
+{
+public:
+    TCritSect () : StatusReg(__get_interrupt_state()) { __disable_interrupt(); }
+    ~TCritSect() { __set_interrupt_state(StatusReg); }
+
+private:
+    TStatusReg StatusReg;
+};
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+//
+//     Priority stuff
+//
+//
+namespace OS
+{
+INLINE inline OS::TProcessMap GetPrioTag(const byte pr) { return static_cast<OS::TProcessMap> (1 << pr); }
+
+#if scmRTOS_PRIORITY_ORDER == 0
+    INLINE inline byte GetHighPriority(TProcessMap pm)
+    {
+        byte pr = 0;
+
+        while( !(pm & 0x0001) )
+        {
+            pr++;
+            pm >>= 1;
+        }
+        return pr;
+    }
+#else
+    INLINE inline byte GetHighPriority(TProcessMap pm) { return (31 - __clz(pm)); }
+#endif // scmRTOS_PRIORITY_ORDER
+}
+
+//-----------------------------------------------------------------------------
+//
+//     Interrupt and Interrupt Service Routines support
+//
+INLINE inline TStatusReg GetInterruptState( )             { return __get_interrupt_state(); }
+INLINE inline void       SetInterruptState(TStatusReg sr) { __set_interrupt_state(sr);      }
+
+INLINE inline void EnableInterrupts()  { __enable_interrupt();  }
+INLINE inline void DisableInterrupts() { __disable_interrupt(); }
+
+
+namespace OS
+{
+    INLINE inline void EnableContextSwitch()  { EnableInterrupts(); }
+    INLINE inline void DisableContextSwitch() { DisableInterrupts(); }
+}
+
+#include <OS_Kernel.h>
+
+namespace OS
+{
+    //--------------------------------------------------------------------------
+    //
+    //      NAME       :   OS ISR support 
+    //
+    //      PURPOSE    :   Implements common actions on interrupt enter and exit 
+    //                     under the OS
+    //
+    //      DESCRIPTION:
+    //
+    //
+    class TISRW
+    {
+    public:
+        INLINE  TISRW()  { ISR_Enter(); }
+        INLINE  ~TISRW() { ISR_Exit();  }
+
+    private:
+        //-----------------------------------------------------
+        INLINE void ISR_Enter()
+        {
+            TCritSect cs;
+            Kernel.ISR_NestCount++;
+        }
+        //-----------------------------------------------------
+        INLINE void ISR_Exit()
+        {
+            TCritSect cs;
+            if(--Kernel.ISR_NestCount) return;
+            Kernel.SchedISR();
+        }
+        //-----------------------------------------------------
+    };
+
+    // No software interrupt stack switching provided,
+    // TISRW_SS declared to be the same as TISRW for porting compability
+    #define TISRW_SS    TISRW
+    
+} // ns OS
+//-----------------------------------------------------------------------------
+
+#endif // scmRTOS_CORTEXM3_H
+//-----------------------------------------------------------------------------
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/CortexM3/OS_Target_asm.s	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,178 @@
+; ******************************************************************************
+; *
+; *     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+; *
+; *     NICKNAME:  scmRTOS
+; *
+; *     PROCESSOR: ARM Cortex-M3 
+; *
+; *     TOOLKIT:   EWARM (IAR Systems)
+; *               
+; *     PURPOSE:   Target Dependent Low-Level Stuff
+; *               
+; *     Version: 3.10
+; *
+; *     $Revision: 195 $
+; *     $Date:: 2008-06-19 #$
+; *
+; *     Copyright (c) 2003-2010, Harry E. Zhurov
+; *
+; *     Permission is hereby granted, free of charge, to any person 
+; *     obtaining  a copy of this software and associated documentation 
+; *     files (the "Software"), to deal in the Software without restriction, 
+; *     including without limitation the rights to use, copy, modify, merge, 
+; *     publish, distribute, sublicense, and/or sell copies of the Software, 
+; *     and to permit persons to whom the Software is furnished to do so, 
+; *     subject to the following conditions:
+; *
+; *     The above copyright notice and this permission notice shall be included 
+; *     in all copies or substantial portions of the Software.
+; *
+; *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+; *     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+; *     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+; *     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+; *     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+; *     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 
+; *     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+; *
+; *     =================================================================
+; *     See http://scmrtos.sourceforge.net for documentation, latest
+; *     information, license and contact details.
+; *     =================================================================
+; *
+; ******************************************************************************
+; *     Ported by Andrey Chuikin, Copyright (c) 2008-2010
+
+; #include "scmRTOS_TARGET_CFG.h"
+
+; -----------------------------------------------------------------------------
+;   PUBLIC FUNCTIONS
+;
+    EXTERN  OS_ContextSwitchHook
+
+    EXPORT  OS_Start
+    EXPORT  PendSV_Handler
+
+; -----------------------------------------------------------------------------
+;   EQUATES
+;
+NVIC_INT_CTRL        EQU     0xE000ED04  ; Interrupt control state register.
+NVIC_PENDSVSET       EQU     0x10000000  ; Value to trigger PendSV exception.
+
+NVIC_SYSPRI14        EQU     0xE000ED22  ; System priority register (priority 14).
+NVIC_PENDSV_PRI      EQU           0xFF  ; PendSV priority value (lowest).
+NVIC_SYSPRI15        EQU     0xE000ED23  ; System priority register (priority 15).
+NVIC_ST_PRI          EQU           0xFF  ; SysTick priority value (lowest).
+
+NVIC_ST_CTRL         EQU    0xE000E010   ; SysTick Ctrl & Status Reg.
+NVIC_ST_RELOAD       EQU    0xE000E014   ; SysTick Reload  Value Reg.
+NVIC_ST_CTRL_CLK_SRC EQU    0x00000004   ; Clock Source.
+NVIC_ST_CTRL_INTEN   EQU    0x00000002   ; Interrupt enable.
+NVIC_ST_CTRL_ENABLE  EQU    0x00000001   ; Counter mode.
+
+; should be the same as in scmRTOS_TARGET_CFG.h
+SYSTICKFREQ          EQU    100000000
+SYSTICKINTRATE       EQU    1000
+
+; -----------------------------------------------------------------------------
+;       CODE GENERATION DIRECTIVES
+; 
+        AREA TEXT, CODE, READONLY
+        THUMB
+
+; -----------------------------------------------------------------------------
+;       HANDLE PendSV EXCEPTION
+;       void PendSV_Handler(void)
+; 
+;  Note(s) : 1) PendSV is used to cause a context switch.  This is a recommended method for performing
+;               context switches with Cortex-M3.  This is because the Cortex-M3 auto-saves half of the
+;               processor context on any exception, and restores same on return from exception.  So only
+;               saving of R4-R11 is required and fixing up the stack pointers.  Using the PendSV exception
+;               this way means that context saving and restoring is identical whether it is initiated from
+;               a thread or occurs due to an interrupt or exception.
+; 
+;            2) Pseudo-code is:
+;               a) Get the process SP, if 0 then skip (goto f) the saving part (first context switch);
+;               b) Save remaining regs r4-r11 on process stack;
+;               c) Call OS_ContextSwitchHook for save current task SP and get new task SP;
+;               d) Restore R4-R11 from new process stack;
+;               e) Perform exception return which will restore remaining context.
+;               f) Get SP for the first context switch (R2 hold it);
+;                  run SysTick; goto d);
+; 
+;            3) On entry into PendSV handler:
+;               a) The following have been saved on the process stack (by processor):
+;                  xPSR, PC, LR, R12, R0-R3
+;               b) Processor mode is switched to Handler mode (from Thread mode)
+;               c) Stack is Main stack (switched from Process stack)
+; 
+;            4) Since PendSV is set to lowest priority in the system (by OS_Start() below), we
+;               know that it will only be run when no other exception or interrupt is active, and
+;               therefore safe to assume that context being switched out was using the process stack (PSP).
+; 
+PendSV_Handler
+    CPSID   I                 ;  Prevent interruption during context switch
+    MRS     R0, PSP           ;  PSP is process stack pointer
+    CBZ     R0, nosave        ;  Skip register save the first time    
+
+    STMDB R0!, {R4-R11}       ;  Save remaining regs r4-11 on process stack
+    ;  At this point, entire context of process has been saved                                                            
+
+    PUSH    {R14}                        ;  Save LR exc_return value
+    LDR     R1, =OS_ContextSwitchHook    ;  OS_ContextSwitchHook();
+    BLX     R1
+    POP     {R14}
+    
+ContextRestore
+    ;  R0 is new process SP;
+    LDMIA R0!, {R4-R11}         ;  Restore r4-11 from new process stack
+    MSR     PSP, R0           ;  Load PSP with new process SP
+    ORR     LR, LR, #0x04     ;  Ensure exception return uses process stack
+    CPSIE   I
+    BX      LR                ;  Exception return will restore remaining context
+nosave
+    MOV R0, R2                ;  R2 hold the first task SP
+    
+    LDR     R1, =NVIC_ST_CTRL ;  Enable and run SysTick
+    LDR     R2, =(NVIC_ST_CTRL_CLK_SRC | NVIC_ST_CTRL_INTEN | NVIC_ST_CTRL_ENABLE)
+    STR     R2, [R1]
+    
+    B   ContextRestore
+
+   
+; -----------------------------------------------------------------------------
+;       START MULTITASKING
+;       void OS_Start(TStackItem* sp)
+; 
+;  Note(s) : 1) OS_Start() MUST:
+;               a) Setup PendSV and SysTick exception priority to lowest;
+;               b) Setup SysTick (reload value);
+;               c) Enable interrupts (tasks will run with interrupts enabled).
+; 
+OS_Start
+    LDR     R1, =NVIC_SYSPRI14      ;  Set the PendSV exception priority (lowest)
+    LDR     R2, =NVIC_PENDSV_PRI
+    STRB    R2, [R1]
+    LDR     R1, =NVIC_SYSPRI15      ;  Set the SysTick exception priority (lowest)
+    LDR     R2, =NVIC_ST_PRI
+    STRB    R2, [R1]
+    
+    LDR     R1, =NVIC_ST_RELOAD     ;  Setup SysTick
+    LDR     R2, =(SYSTICKFREQ/SYSTICKINTRATE-1)  
+    STR     R2, [R1]
+
+    MOV     R2, R0                  ;  Save the first task stack
+    MOVS    R0, #0                  ;  Set the PSP to 0 for initial context switch call
+    MSR     PSP, R0
+
+    LDR     R0, =NVIC_INT_CTRL      ;  Trigger the PendSV exception (causes context switch)
+    LDR     R1, =NVIC_PENDSVSET
+    STR     R1, [R0]
+
+    CPSIE   I                       ;  Enable interrupts at processor level
+loop
+    B       loop                    ;  Should never get here
+
+
+    END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/CortexM3/OS_Target_cpp.cpp	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,131 @@
+//******************************************************************************
+//*
+//*     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+//*
+//*     NICKNAME:  scmRTOS
+//*
+//*     PROCESSOR: ARM Cortex-M3 
+//*
+//*     TOOLKIT:   EWARM (IAR Systems)
+//*               
+//*     PURPOSE:   Target Dependent Stuff Source
+//*               
+//*     Version: 3.10
+//*
+//*     $Revision: 195 $
+//*     $Date:: 2008-06-19 #$
+//*
+//*     Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//*     Permission is hereby granted, free of charge, to any person 
+//*     obtaining  a copy of this software and associated documentation 
+//*     files (the "Software"), to deal in the Software without restriction, 
+//*     including without limitation the rights to use, copy, modify, merge, 
+//*     publish, distribute, sublicense, and/or sell copies of the Software, 
+//*     and to permit persons to whom the Software is furnished to do so, 
+//*     subject to the following conditions:
+//*
+//*     The above copyright notice and this permission notice shall be included 
+//*     in all copies or substantial portions of the Software.
+//*
+//*     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+//*     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+//*     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+//*     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+//*     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+//*     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 
+//*     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//*     =================================================================
+//*     See http://scmrtos.sourceforge.net for documentation, latest
+//*     information, license and contact details.
+//*     =================================================================
+//*
+//******************************************************************************
+//*     Ported by Andrey Chuikin, Copyright (c) 2008-2010
+
+
+#include <scmRTOS.h>
+
+using namespace OS;
+
+//------------------------------------------------------------------------------
+//
+//       OS Process's constructor
+//
+//       Performs:  
+//           * initializing process data;
+//           * registering of the process in kernel;
+//           * preparing stack frame;
+//                  
+//
+TBaseProcess::TBaseProcess(TStackItem* Stack, TPriority pr, void (*exec)())
+    : StackPointer(Stack)
+    , Timeout(0)
+    , Priority(pr)
+{
+    Kernel.RegisterProcess(this);
+
+    //---------------------------------------------------------------
+    //
+    //  Prepare Process Stack Frame
+    //
+    *(--StackPointer)  = 0x01000000L;             // xPSR
+    *(--StackPointer)  = reinterpret_cast<dword>(exec); // Entry Point
+    StackPointer -= 14;                           // emulate "push R14,R12,R3,R2,R1,R0,R11-R4"
+    
+    // The code below can be used for debug purpose. In this case comment
+    // line above and uncomment block below.
+/*
+    *(--StackPointer)  = 0xFFFFFFFEL;             // R14 (LR) (init value will cause fault if ever used)
+    *(--StackPointer)  = 0x12121212L;             // R12
+    *(--StackPointer)  = 0x03030303L;             // R3
+    *(--StackPointer)  = 0x02020202L;             // R2
+    *(--StackPointer)  = 0x01010101L;             // R1
+    *(--StackPointer)  = 0x00000000L;             // R0
+
+                                                  // Remaining registers saved on process stack
+    *(--StackPointer)  = 0x11111111L;             // R11
+    *(--StackPointer)  = 0x10101010L;             // R10
+    *(--StackPointer)  = 0x09090909L;             // R9
+    *(--StackPointer)  = 0x08080808L;             // R8
+    *(--StackPointer)  = 0x07070707L;             // R7
+    *(--StackPointer)  = 0x06060606L;             // R6
+    *(--StackPointer)  = 0x05050505L;             // R5
+    *(--StackPointer)  = 0x04040404L;             // R4
+*/
+}
+//------------------------------------------------------------------------------
+//
+//   Idle Process
+//
+typedef process<prIDLE, scmRTOS_IDLE_PROCESS_STACK_SIZE> TIdleProcess;
+
+TIdleProcess IdleProcess;
+
+template<> OS_PROCESS void TIdleProcess::Exec()
+{
+    for(;;)
+    {
+        #if scmRTOS_IDLE_HOOK_ENABLE == 1
+        IdleProcessUserHook();
+        #endif
+    }
+}
+//------------------------------------------------------------------------------
+OS_INTERRUPT void OS::SysTick_Handler()
+{
+    scmRTOS_ISRW_TYPE ISR;
+
+    Kernel.SystemTimer();
+    
+#if scmRTOS_SYSTIMER_NEST_INTS_ENABLE == 0
+    DISABLE_NESTED_INTERRUPTS();
+#endif
+    
+#if scmRTOS_SYSTIMER_HOOK_ENABLE == 1
+    SystemTimerUserHook();
+#endif
+}
+//------------------------------------------------------------------------------
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/CortexM3/commdefs.h	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,71 @@
+//******************************************************************************
+//*
+//*     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+//*
+//*     NICKNAME:  scmRTOS
+//*
+//*     PROCESSOR: ARM Cortex-M3 
+//*
+//*     TOOLKIT:   EWARM (IAR Systems)
+//*
+//*     PURPOSE:   Common Type Definitions
+//*
+//*     Version: 3.10
+//*
+//*     $Revision: 195 $
+//*     $Date:: 2008-06-19 #$
+//*
+//*     Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//*     Permission is hereby granted, free of charge, to any person 
+//*     obtaining  a copy of this software and associated documentation 
+//*     files (the "Software"), to deal in the Software without restriction, 
+//*     including without limitation the rights to use, copy, modify, merge, 
+//*     publish, distribute, sublicense, and/or sell copies of the Software, 
+//*     and to permit persons to whom the Software is furnished to do so, 
+//*     subject to the following conditions:
+//*
+//*     The above copyright notice and this permission notice shall be included 
+//*     in all copies or substantial portions of the Software.
+//*
+//*     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+//*     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+//*     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+//*     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+//*     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+//*     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 
+//*     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//*     =================================================================
+//*     See http://scmrtos.sourceforge.net for documentation, latest
+//*     information, license and contact details.
+//*     =================================================================
+//*
+//******************************************************************************
+//*     Ported by Andrey Chuikin, Copyright (c) 2008-2010
+
+
+#ifndef COMMONDEFS_H
+#define COMMONDEFS_H
+
+#ifndef __IAR_SYSTEMS_ASM__
+
+typedef unsigned char  byte;
+typedef signed char    sbyte;
+typedef unsigned short word;
+typedef unsigned long  dword;
+
+typedef volatile byte  sfr_byte;
+typedef volatile word  sfr_word;
+typedef volatile dword sfr_dword;
+
+#define INLINE _Pragma("inline=forced")
+
+#endif // __IAR_SYSTEMS_ASM__
+
+#endif // COMMONDEFS_H
+
+//-----------------------------------------------------------------------------
+
+/*============================================================================*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/CortexM3/device.h	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,60 @@
+//******************************************************************************
+//*
+//*     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+//*
+//*     NICKNAME:  scmRTOS
+//*
+//*     PROCESSOR: ARM Cortex-M3 
+//*
+//*     TOOLKIT:   EWARM (IAR Systems)
+//*
+//*     PURPOSE:   Device Definitions
+//*
+//*     Version: 3.10
+//*
+//*     $Revision: 196 $
+//*     $Date:: 2008-06-19 #$
+//*
+//*     Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//*     Permission is hereby granted, free of charge, to any person 
+//*     obtaining  a copy of this software and associated documentation 
+//*     files (the "Software"), to deal in the Software without restriction, 
+//*     including without limitation the rights to use, copy, modify, merge, 
+//*     publish, distribute, sublicense, and/or sell copies of the Software, 
+//*     and to permit persons to whom the Software is furnished to do so, 
+//*     subject to the following conditions:
+//*
+//*     The above copyright notice and this permission notice shall be included 
+//*     in all copies or substantial portions of the Software.
+//*
+//*     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+//*     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+//*     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+//*     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+//*     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+//*     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 
+//*     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//*     =================================================================
+//*     See http://scmrtos.sourceforge.net for documentation, latest
+//*     information, license and contact details.
+//*     =================================================================
+//*
+//******************************************************************************
+//*     Ported by Andrey Chuikin, Copyright (c) 2008-2010
+
+#ifndef DEVICE_H
+#define DEVICE_H
+
+#include <commdefs.h>
+
+//------------------------------------------------------------------------------
+// Definitions for some processor registers in order to not include specific
+// header file for various Cortex-M3 processor derivatives.
+#define CPU_ICSR            ( ( sfr_dword *) 0xE000ED04 )   // Interrupt Control State Register
+#define CPU_SYSTICKCSR      ( ( sfr_dword *) 0xE000E010 )   // SysTick Control and Status Register
+#define CPU_SYSTICKCSR_EINT 0x02                            // Bit for enable/disable SysTick interrupt
+
+
+#endif  /* DEVICE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/scmRTOS_TARGET_CFG.h	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,102 @@
+//******************************************************************************
+//*
+//*     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+//*
+//*     NICKNAME:  scmRTOS
+//*
+//*     PROCESSOR: ARM Cortex-M3 
+//*
+//*     TOOLKIT:   EWARM (IAR Systems)
+//*
+//*     PURPOSE:   Project Level Target Extensions Config
+//*
+//*     Version: 3.10
+//*
+//*     $Revision: 196 $
+//*     $Date:: 2008-06-19 #$
+//*
+//*     Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//*     Permission is hereby granted, free of charge, to any person 
+//*     obtaining  a copy of this software and associated documentation 
+//*     files (the "Software"), to deal in the Software without restriction, 
+//*     including without limitation the rights to use, copy, modify, merge, 
+//*     publish, distribute, sublicense, and/or sell copies of the Software, 
+//*     and to permit persons to whom the Software is furnished to do so, 
+//*     subject to the following conditions:
+//*
+//*     The above copyright notice and this permission notice shall be included 
+//*     in all copies or substantial portions of the Software.
+//*
+//*     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+//*     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+//*     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+//*     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+//*     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+//*     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 
+//*     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//*     =================================================================
+//*     See http://scmrtos.sourceforge.net for documentation, latest
+//*     information, license and contact details.
+//*     =================================================================
+//*
+//******************************************************************************
+//*     mbed port by Igor Skochinsky
+
+#ifndef  scmRTOS_TARGET_CFG_H
+#define  scmRTOS_TARGET_CFG_H
+
+#include "device.h"
+
+// Define SysTick clock frequency and its interrupt rate in Hz.
+#define SYSTICKFREQ     100000000
+#define SYSTICKINTRATE  1000
+
+//------------------------------------------------------------------------------
+//
+//       System Timer stuff
+//
+//
+namespace OS
+{
+extern "C" void SysTick_Handler();
+}
+
+#define  LOCK_SYSTEM_TIMER()    ( *CPU_SYSTICKCSR &= ~CPU_SYSTICKCSR_EINT )
+#define  UNLOCK_SYSTEM_TIMER()  ( *CPU_SYSTICKCSR |=  CPU_SYSTICKCSR_EINT )
+
+//------------------------------------------------------------------------------
+//
+//       Context Switch ISR stuff
+//
+//
+namespace OS
+{
+#if scmRTOS_IDLE_HOOK_ENABLE == 1
+    void IdleProcessUserHook();
+#endif
+
+#if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
+
+    INLINE inline void RaiseContextSwitch() { *CPU_ICSR |= 0x10000000; }
+
+    #define ENABLE_NESTED_INTERRUPTS()
+    
+    #if scmRTOS_SYSTIMER_NEST_INTS_ENABLE == 0
+        #define DISABLE_NESTED_INTERRUPTS() TCritSect cs
+    #else
+        #define DISABLE_NESTED_INTERRUPTS()
+    #endif
+
+#else
+    #error "Cortex-M3 port supports software interrupt switch method only!"
+
+#endif // scmRTOS_CONTEXT_SWITCH_SCHEME
+
+}
+//-----------------------------------------------------------------------------
+
+#endif // scmRTOS_TARGET_CFG_H
+//-----------------------------------------------------------------------------
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS_config.h	Mon Sep 27 22:51:19 2010 +0000
@@ -0,0 +1,132 @@
+//******************************************************************************
+//*
+//*     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+//*
+//*     NICKNAME:  scmRTOS
+//*
+//*     PROCESSOR: ARM Cortex-M3 
+//*
+//*     TOOLKIT:   EWARM (IAR Systems)
+//*
+//*     PURPOSE:   Project Level Configuration
+//*
+//*     Version: 3.10
+//*
+//*     $Revision: 196 $
+//*     $Date:: 2008-06-19 #$
+//*
+//*     Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//*     Permission is hereby granted, free of charge, to any person 
+//*     obtaining  a copy of this software and associated documentation 
+//*     files (the "Software"), to deal in the Software without restriction, 
+//*     including without limitation the rights to use, copy, modify, merge, 
+//*     publish, distribute, sublicense, and/or sell copies of the Software, 
+//*     and to permit persons to whom the Software is furnished to do so, 
+//*     subject to the following conditions:
+//*
+//*     The above copyright notice and this permission notice shall be included 
+//*     in all copies or substantial portions of the Software.
+//*
+//*     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+//*     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+//*     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+//*     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
+//*     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+//*     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 
+//*     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//*     =================================================================
+//*     See http://scmrtos.sourceforge.net for documentation, latest
+//*     information, license and contact details.
+//*     =================================================================
+//*
+//******************************************************************************
+//*     Ported by Andrey Chuikin, Copyright (c) 2008-2010
+
+#ifndef  scmRTOS_CONFIG_H
+#define  scmRTOS_CONFIG_H
+
+#ifndef __IAR_SYSTEMS_ASM__
+#include <commdefs.h>
+
+typedef word TTimeout;
+
+#endif // __IAR_SYSTEMS_ASM__
+
+#include "device.h"
+//------------------------------------------------------------------------------
+//
+//    Specify scmRTOS Process Count. Must be less than 31
+//
+//
+#define  scmRTOS_PROCESS_COUNT                  1
+
+//-----------------------------------------------------------------------------
+//
+//    scmRTOS System Timer 
+// 
+//    Nested Interrupts enable macro. Value 1 means that interrupts are
+//    globally enabled within System Timer ISR (this is default for Cortex-M3).
+// 
+//
+#define scmRTOS_SYSTIMER_NEST_INTS_ENABLE 1
+
+//-----------------------------------------------------------------------------
+//
+//    scmRTOS System Timer Tick Counter Enable
+//
+//
+#define  scmRTOS_SYSTEM_TICKS_ENABLE        1
+
+
+//-----------------------------------------------------------------------------
+//
+//    scmRTOS System Timer Hook
+//
+//
+#define  scmRTOS_SYSTIMER_HOOK_ENABLE       1
+
+//-----------------------------------------------------------------------------
+//
+//    scmRTOS Idle Process Hook
+//
+//
+#define  scmRTOS_IDLE_HOOK_ENABLE           1
+
+//-----------------------------------------------------------------------------
+//
+//    scmRTOS Idle Process Stack size (in bytes)
+//    (20 * sizeof(TStackItem)) - it's a minimum allowed value.
+//
+#define scmRTOS_IDLE_PROCESS_STACK_SIZE       (20 * sizeof(TStackItem))
+
+//-----------------------------------------------------------------------------
+//
+//    scmRTOS Priority Order
+//
+//    This macro defines the order of the process's priorities. Default,
+//    the ascending order is used. Alternatively, the descending priority 
+//    order can be used. On some platforms the descending order is preferred
+//    because of performance.   
+// 
+//    Default (corresponding to ascending order) value of macro is 0.  
+//    Alternative (corresponding to descending order) value of macro is 1.  
+//
+//    On Cortex-M3 the descending order is preferred for performance reason.
+//
+#define  scmRTOS_PRIORITY_ORDER 1
+
+//-----------------------------------------------------------------------------
+//
+//    scmRTOS Context Switch User Hook enable
+// 
+//    The macro enables/disables user defined hook called from system
+//    Context Switch Hook function.
+//
+//
+#define  scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE  0
+
+
+#endif // scmRTOS_CONFIG_H
+//-----------------------------------------------------------------------------