Library for the Grove Earbud Heartrate Sensor

Dependents:   BLE_Police_HRM_Earbud df-2014-salesforce-hrm-k64f BLE_HeartRate_ppm emoSound ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GroveEarbudSensor.cpp Source File

GroveEarbudSensor.cpp

00001 /* Copyright C2014 ARM, MIT License
00002  *
00003  * Author: Doug Anson (doug.anson@arm.com)
00004  *
00005  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00006  * and associated documentation files the "Software", to deal in the Software without restriction,
00007  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
00008  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
00009  * furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in all copies or
00012  * substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00015  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00016  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00017  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00018  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00019  */
00020  
00021  #include "GroveEarbudSensor.h"
00022  
00023  // Console logging
00024  //#define LOG_CONSOLE(...) { if (this->m_pc != NULL) this->m_pc->printf(__VA_ARGS__); }
00025  #define LOG_CONSOLE(...) { ; }
00026 
00027  // Our instance
00028  GroveEarbudSensor *_grove_earbud_sensor_instance = NULL;
00029  
00030  // interrupt function
00031  void __grove_earbud_sensor_interrupt() { if (_grove_earbud_sensor_instance != NULL) _grove_earbud_sensor_instance->interrupt(); }
00032  
00033  // constructor
00034  GroveEarbudSensor::GroveEarbudSensor(InterruptIn *rx,RawSerial *pc) {
00035      _grove_earbud_sensor_instance       = this;
00036      this->m_rx                          = rx;
00037      this->m_pc                          = pc;
00038      this->m_sub                         = 0;
00039      this->m_counter                     = 0;
00040      this->m_data_effect                 = true;
00041      this->m_cb_fn                       = NULL;
00042      this->m_cb_data                     = NULL;
00043      this->m_heartrate                   = HEARTRATE_OFF;
00044      this->m_timer                       = new Timer();
00045      this->m_internal_interrupt_instance = false;
00046      
00047      // register the interrupt handler
00048      if (this->m_rx != NULL) this->m_rx->rise(&__grove_earbud_sensor_interrupt);
00049           
00050      // start the timer and initialize the summation array
00051      if (this->m_timer != NULL) {
00052          // start the timer
00053          this->m_timer->start();
00054      
00055          // initialize the summation array
00056          this->initSummationArray();
00057      }
00058  }
00059  
00060  // constructor
00061  GroveEarbudSensor::GroveEarbudSensor(PinName interrupt_pin,RawSerial *pc) {
00062      _grove_earbud_sensor_instance       = this;
00063      this->m_rx                          = new InterruptIn(interrupt_pin);
00064      this->m_pc                          = pc;
00065      this->m_sub                         = 0;
00066      this->m_counter                     = 0;
00067      this->m_data_effect                 = true;
00068      this->m_cb_fn                       = NULL;
00069      this->m_cb_data                     = NULL;
00070      this->m_heartrate                   = HEARTRATE_OFF;
00071      this->m_timer                       = new Timer();
00072      this->m_internal_interrupt_instance = true;
00073      
00074      // register the interrupt handler
00075      if (this->m_rx != NULL) this->m_rx->rise(&__grove_earbud_sensor_interrupt);
00076           
00077      // start the timer and initialize the summation array
00078      if (this->m_timer != NULL) {
00079          // start the timer
00080          this->m_timer->start();
00081      
00082          // initialize the summation array
00083          this->initSummationArray();
00084      }
00085  }
00086  
00087  // destructor
00088  GroveEarbudSensor::~GroveEarbudSensor() {
00089      if (this->m_timer != NULL) delete this->m_timer;
00090      if (this->m_internal_interrupt_instance == true && this->m_rx != NULL) delete this->m_rx;
00091  }
00092  
00093  // initialize the summation array
00094  void GroveEarbudSensor::initSummationArray(void) {
00095     for(int i=0;i<(NUM_SLOTS-1);++i) this->m_temp[i]=0;
00096     this->m_temp[NUM_SLOTS-1] = this->m_timer->read_ms();
00097  }
00098  
00099  // register callback 
00100  void GroveEarbudSensor::registerCallback(GroveEarbudSensorCallback *cb_fn,void *cb_data) {
00101      this->m_cb_fn = cb_fn;
00102      this->m_cb_data = cb_data;
00103  }
00104  
00105  // get the current heartrate
00106  float GroveEarbudSensor::getHeartRate(void) { return this->m_heartrate; }
00107 
00108  // summation method + internal callback to fire any registered callback fns
00109  void GroveEarbudSensor::sumAndInvokeCallback(void) {
00110    if(this->m_data_effect) {
00111       // summation
00112       int tmp = 60 * (NUM_SLOTS-1) * 1000;
00113       this->m_heartrate = tmp/(this->m_temp[NUM_SLOTS-1]-this->m_temp[0]);
00114       
00115       // DEBUG/Log
00116       if (this->m_heartrate > 0) LOG_CONSOLE("heartrate: %d bpm\r\n",this->m_heartrate);
00117       
00118       // invoke any callbacks we might have
00119       if (this->m_cb_fn != NULL) {
00120           // invoke the callback
00121           LOG_CONSOLE("invoking callback with heartrate = %d bpm\r\n",this->m_heartrate);
00122           (*this->m_cb_fn)(this->m_heartrate,this->m_cb_data);
00123       }
00124    }
00125    this->m_data_effect = 1;  //sign bit
00126 }
00127 
00128  // interrupt() method for earbud
00129  void GroveEarbudSensor::interrupt() {
00130     this->m_temp[this->m_counter] = this->m_timer->read_ms();
00131     switch(this->m_counter) {
00132         case 0:
00133             this->m_sub=this->m_temp[this->m_counter]-this->m_temp[NUM_SLOTS-1];
00134             break;
00135         default:
00136             this->m_sub=this->m_temp[this->m_counter]-this->m_temp[this->m_counter-1];
00137             break;
00138     }
00139     if(this->m_sub > HEARTPULSE_DUTY) { 
00140         this->m_data_effect = 0; //sign bit
00141         this->m_counter = 0;
00142         LOG_CONSOLE("heartrate measure error. Restarting timer..\r\n");
00143         this->initSummationArray();
00144         this->m_timer->stop();
00145         this->m_timer->start();
00146     }
00147     if (this->m_counter >= (NUM_SLOTS-1) && this->m_data_effect) {
00148         this->m_counter = 0;
00149         this->sumAndInvokeCallback();
00150     }
00151     else if(this->m_counter < (NUM_SLOTS-1) && this->m_data_effect) {
00152         this->m_counter++;
00153     }
00154     else {
00155         this->m_counter = 0;
00156         this->m_data_effect = 1;
00157     }
00158  }
00159