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