1 /*
2  * Author: Andrei Vasiliu <andrei.vasiliu@intel.com>
3  * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
4  * Copyright (c) 2015 Intel Corporation.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 #include <string>
27 #include <stdexcept>
28 #include <unistd.h>
29 #include <stdlib.h>
30 
31 #include "pulsensor.h"
32 
33 #if defined(JAVACALLBACK)
Pulsensor(Callback * obj_call)34 Pulsensor::Pulsensor (Callback *obj_call) : pin_ctx(0)
35 {
36     obj_callback = obj_call;
37 
38     sample_counter = 0;
39     last_beat_time = 0;
40     threshold      = 512;
41     ibi            = 600;
42     trough         = 512;
43     peak           = 512;
44     is_pulse       = FALSE;
45     ret            = FALSE;
46     bpm            = 0;
47     qs             = FALSE;
48     apmlitude      = 100;
49 }
50 #else
Pulsensor(callback_handler handler)51 Pulsensor::Pulsensor (callback_handler handler) : pin_ctx(0)
52 {
53     callback = handler;
54 
55     sample_counter = 0;
56     last_beat_time = 0;
57     threshold      = 512;
58     ibi            = 600;
59     trough         = 512;
60     peak           = 512;
61     is_pulse       = FALSE;
62     ret            = FALSE;
63     bpm            = 0;
64     qs             = FALSE;
65     apmlitude      = 100;
66 }
67 #endif
68 
start_sampler()69 void Pulsensor::start_sampler ()
70 {
71     int error;
72     ctx_counter++;
73     usleep (100000);
74     error = pthread_create (&(sample_thread), NULL, &Pulsensor::do_sample, this);
75     if (error != 0) {
76         printf ("ERROR : Cannot created sampler thread.\n");
77     }
78 }
79 
stop_sampler()80 void Pulsensor::stop_sampler () {
81     ctx_counter--;
82 }
83 
do_sample(void * arg)84 void *Pulsensor::do_sample (void *arg) {
85     int data_from_sensor;
86     clbk_data callback_data;
87 
88     Pulsensor *pulsensor = static_cast<Pulsensor *>(arg);
89 
90     while (pulsensor->ctx_counter) {
91         data_from_sensor = pulsensor->pin_ctx.read ();
92         pulsensor->ret = FALSE;
93 
94         pulsensor->sample_counter += 2;
95         int N = pulsensor->sample_counter - pulsensor->last_beat_time;
96 
97         if (data_from_sensor < pulsensor->threshold &&
98             N > ( pulsensor->ibi / 5)* 3) {
99             if (data_from_sensor < pulsensor->trough) {
100                 pulsensor->trough = data_from_sensor;
101             }
102         }
103 
104         if (data_from_sensor > pulsensor->threshold &&
105             data_from_sensor > pulsensor->peak) {
106             pulsensor->peak = data_from_sensor;
107         }
108 
109         if (N > 250) {
110             // printf ("(NO_GDB) DEBUG\n");
111             if ( (data_from_sensor > pulsensor->threshold) &&
112                     (pulsensor->is_pulse == FALSE) &&
113                     (N > (pulsensor->ibi / 5)* 3) ) {
114                 pulsensor->is_pulse = callback_data.is_heart_beat = TRUE;
115 #if defined(JAVACALLBACK)
116                 pulsensor->obj_callback->run(callback_data);
117 #else
118                 pulsensor->callback(callback_data);
119 #endif
120 
121                 pulsensor->ibi = pulsensor->sample_counter - pulsensor->last_beat_time;
122                 pulsensor->last_beat_time = pulsensor->sample_counter;
123 
124                 // second beat
125                 if (pulsensor->second_beat) {
126                     pulsensor->second_beat = FALSE;
127                     for (int i = 0; i <= 9; i++) {
128                         pulsensor->ibi_rate[i] = pulsensor->ibi;
129                     }
130                 }
131 
132                 // first beat
133                 if (pulsensor->first_beat) {
134                     pulsensor->first_beat  = FALSE;
135                     pulsensor->second_beat = TRUE;
136                     pulsensor->ret = TRUE;
137                 } else {
138                     uint32_t running_total = 0;
139                     for(int i = 0; i <= 8; i++){
140                         pulsensor->ibi_rate[i] = pulsensor->ibi_rate[i+1];
141                         running_total += pulsensor->ibi_rate[i];
142                     }
143 
144                     pulsensor->ibi_rate[9] = pulsensor->ibi;
145                     running_total += pulsensor->ibi_rate[9];
146                     running_total /= 10;
147                     pulsensor->bpm = 60000 / running_total;
148                     pulsensor->qs = TRUE;
149                 }
150             }
151         }
152 
153         if (pulsensor->ret == FALSE) {
154             if (data_from_sensor < pulsensor->threshold &&
155                 pulsensor->is_pulse == TRUE) {
156                 pulsensor->is_pulse = callback_data.is_heart_beat = FALSE;
157 #if defined(JAVACALLBACK)
158                 pulsensor->obj_callback->run(callback_data);
159 #else
160                 pulsensor->callback(callback_data);
161 #endif
162                 pulsensor->is_pulse   = FALSE;
163                 pulsensor->apmlitude  = pulsensor->peak - pulsensor->trough;
164                 pulsensor->threshold  = pulsensor->apmlitude / 2 + pulsensor->trough;
165                 pulsensor->peak       = pulsensor->threshold;
166                 pulsensor->trough     = pulsensor->threshold;
167             }
168 
169             if (N > 2500) {
170                 pulsensor->threshold      = 512;
171                 pulsensor->peak           = 512;
172                 pulsensor->trough         = 512;
173                 pulsensor->last_beat_time = pulsensor->sample_counter;
174                 pulsensor->first_beat     = TRUE;
175                 pulsensor->second_beat    = FALSE;
176             }
177         }
178 
179         usleep (2000);
180     }
181     return NULL;
182 }
183